/* * The implementation of clay golem monsters. */ #include #include #include "mon.h" #include "vars.h" #include "dice.h" #include "damage.h" #include "structs.h" typedef struct priv_C PRIV_C; struct priv_C { unsigned int lasthit; } ; /* * The clay golem tick method. Just use the standard animal tick, but * fiddle the heal value first. Clay golems don't heal when in active * combat, but heal faster and faster as it's been longer and longer * since combat. We implement this by setting the heal amount to a * random value less than the time since it last got hit. * * XXX Should we use std_human_tick? */ static void clay_golem_tick(MONST *m) { int n; n = m->age - ((PRIV_C *)m->priv)->lasthit; m->heal = (n > 1) ? rnd((n>100000)?100000:n) : 0; std_animal_tick(m); } /* * The clay golem bemoved method. Nothing to do here. */ static void clay_golem_bemoved(MONST *m __attribute__((__unused__))) { } /* * The clay golem name method. */ static const char *clay_golem_name(MONST *m __attribute__((__unused__))) { return("the clay golem"); } /* * The clay golem Name method. */ static const char *clay_golem_Name(MONST *m __attribute__((__unused__))) { return("The clay golem"); } /* * The clay golem attack method. They have a decent hit chance. */ static int clay_golem_attack(MONST *m __attribute__((__unused__))) { return(rnd(75)); } /* * The clay golem defend method. They have poor defense (largely from * their large size). */ static int clay_golem_defend(MONST *m __attribute__((__unused__))) { return(rnd(25)); } /* * The clay golem damage method. They do relatively nasty damage. * This is normally DF_MAGICONLY damage, but if the golem has been * canceled it's ordinary damage. */ static DAMAGE clay_golem_givedamage(MONST *m, int dd __attribute__((__unused__))) { return(damage_simple(roll("5d1000"),DK_ORDINARY,(m->baseflags&MBF_CANCEL)?0:DF_MAGICONLY)); } /* * The clay golem takedamage method. They have a custom version of * this because they have damage reduction and because of last-hit * tracking (which affects healing - see above). */ static TDRV clay_golem_takedamage(MONST *m, DAMAGE dmg) { int dr; dr = rnd(1000); damage_reduction(&dmg,dr); if (! dmg.elts) { damage_free(dmg); return((TDRV){.taken=0,.flags=0}); } ((PRIV_C *)m->priv)->lasthit = m->age; return(std_takedamage(m,dmg)); } /* * The clay golem destroy method. */ static void clay_golem_destroy(MONST *m) { free(m->priv); std_destroy(m); } /* * The clay golem MONOPS vector. */ static MONOPS ops = { &clay_golem_tick, &clay_golem_bemoved, &clay_golem_name, &clay_golem_Name, &clay_golem_attack, &clay_golem_defend, &clay_golem_givedamage, &clay_golem_takedamage, &std_kill, &clay_golem_destroy }; /* * Create a new clay golem. */ static MONST *new_C(MONST *m, LEVEL *lv __attribute__((__unused__))) { PRIV_C *p; p = malloc(sizeof(PRIV_C)); p->lasthit = m->age; m->priv = p; m->symbol = 'C'; m->maxhp = 25000 + roll("2d5000"); m->baseflags = Z_mad ? MBF_TRACKING : 0; m->ops = &ops; return(m); } /* * The clay golem ctl method. */ static void monctl_C(MONST *m, int op, ...) { va_list ap; va_start(ap,op); switch (op) { case MCTL_AGGR: { int ag; ag = va_arg(ap,int); if (ag) m->baseflags |= MBF_TRACKING; else m->baseflags &= ~MBF_TRACKING; } break; } va_end(ap); } /* * The clay golem MTINFO. */ #define basespeed_C TIMESCALE #define baseheal_C 0 // fiddled in clay_golem_tick #define exp_C 10000 MTINFO mtinfo_C = MTINFO_INIT(C);