/* * The implementation of rings. */ #include #include "obj.h" #include "util.h" #include "vars.h" #include "pline.h" #include "param.h" #include "effect.h" #include "format.h" #include "structs.h" #include "objtypes.h" #include "obj-ring.h" typedef struct ring RING; typedef struct ringeffect RINGEFFECT; /* * Private data for a ring. */ struct ring { MONST *wornby; RINGEFFECT *e; } ; /* * Private data for a ring-generated effect. */ struct ringeffect { MONST *m; EFFECT *eff; OBJ *o; } ; static void apply_ring(MONST *m, void *rev) { RINGEFFECT *re; re = rev; switch (re->o->type) { // case OBJ_RING_OF_FIRE_RESISTANCE: // case OBJ_RING_OF_PROTECTION: case OBJ_RING_OF_REGENERATION: m->heal += 150; break; case OBJ_RING_OF_SEE_INVISIBLE: m->flags |= MF_SEE_INVISIBLE; break; // case OBJ_RING_OF_SLOW_DIGESTION: // case OBJ_RING_OF_STEALTH: // case OBJ_RING_OF_TELEPORT_CONTROL: case OBJ_RING_OF_VAMPIRIC_REGENERATION: m->flags |= MF_VAMP_REGEN; break; } } static void death_ring(MONST *m __attribute__((__unused__)), void *rev) { free(rev); } static EFFECTOPS effops_ring = EFFECTOPS_INIT(ring); void ring_remove_all(MONST *m) { int i; for (i=MAXRINGS-1;i>=0;i--) if (m->rings[i]) ring_remove(m,m->rings[i]); } void ring_put(MONST *m, OBJ *o) { RING *r; int i; RINGEFFECT *e; if (objtypes[o->type].class != OC_RING) panic("putting on non-ring"); if (m->rings[MAXRINGS-1]) panic("putting on too many rings"); r = o->private; if (r->wornby) panic("putting on already-worn ring"); for (i=MAXRINGS-1;(i>=0)&&!m->rings[i];i--) ; i ++; pline("using rings[%d]",i); if ((i < 0) || (i >= MAXRINGS) || m->rings[i]) panic("impossible ring slot"); m->rings[i] = o; r->wornby = m; e = malloc(sizeof(RINGEFFECT)); e->m = m; e->o = o; e->eff = effect_add(m,e,&effops_ring); r->e = e; } void ring_remove(MONST *m, OBJ *o) { RING *r; int i; if (objtypes[o->type].class != OC_RING) panic("removing non-ring"); r = o->private; if (! r->wornby) panic("removing non-worn ring"); if (r->wornby != m) panic("removing ring from wrong monster"); for (i=MAXRINGS-1;(i>=0)&&(m->rings[i]!=o);i--) ; if (i < 0) panic("worn ring isn't in rings[]"); pline("found in rings[%d]",i); for (;irings[i] = m->rings[i+1]; m->rings[MAXRINGS-1] = 0; r->wornby = 0; effect_remove(m,r->e->eff); free(r->e); r->e = 0; } int ring_being_worn(OBJ *o) { return(!!((RING *)o->private)->wornby); } /* * The new method for rings. */ static OBJ *new_ring(int type __attribute__((__unused__)), OBJ *o) { RING *r; r = malloc(sizeof(RING)); r->wornby = 0; o->private = r; return(o); } /* * The old method for rings. */ static void old_ring(OBJ *o) { if (((RING *)o->private)->wornby) panic("freeing worn ring"); free(o->private); } static int fmt_cond_ring(char ch, INVOBJ *io) { switch (ch) { case 'W': return(!!((RING *)io->v[0]->private)->wornby); break; } panic("invalid conditional +%c for ring",ch); } static int identified_ring(INVOBJ *io) { return(!!(objtypes[io->v[0]->type].flags&OTF_KNOWN)); } static INVOBJ *identify_ring(INVOBJ *io) { objtypes[io->v[0]->type].flags |= OTF_KNOWN; return(io); } #define format_ring std_format #define fmt_spec_ring panic_fmt_spec #define collapsible_ring never_collapsible #define identical_ring never_identical #define split_ring std_split #define moved_ring noop_moved OBJOPS objops_ring = OBJOPS_INIT(ring);