/* Do not remove the headers from this file! see /USAGE for more info. */ /* Note: we calculate healing on a "need to know" basis. This allows us * to pretend you've been healing ever N seconds, without wasting CPU time * actually incrementing something every N seconds. * With a large number of wounded players/monsters on a MUD, this can be * a huge CPU gain. */ inherit __DIR__ "diagnose_msg"; void die(); varargs int query_health(string unused); int query_asleep(); int query_stunned(); private int health = 1; private int max_health = 1; private nosave int health_time = time(); private int heal_rate = 15; private int dead = 0; void set_heal_rate(int x) { if(x < 0) x = 0; /* a number of things depend upon this */ heal_rate = x; } int query_heal_rate() { return heal_rate; } //:FUNCTION set_max_health // void set_max_health(int x); // Set the maximum number of hit points of a monster, and also set it's // hit points to the new max. void set_max_health(int x) { health = max_health = x; health_time = time(); /* old healing irrelevant */ } //:FUNCTION kill_us // void kill_us() // Call this function to kill an adversary completely. void kill_us() { dead = 1; die(); } //:FUNCTION set_health // void set_health(int x); // Set the hit points of a monster. Usually, you want to use heal_us() or // set_max_health instead. // see also: set_max_health void set_health(int x) { if(x > max_health) error("Attempt to set health > max_health.\n"); if(health == 0) return; health = x; if(health <= 0) kill_us(); else health_time = time(); /* old healing irrelevant */ } //:FUNCTION hurt_us // varargs int hurt_us(int x, string unused); // Hurt us a specified amount. varargs int hurt_us(int x, string unused) { query_health(); /* must update healing first */ health -= x; if(health <= 0) kill_us(); return x; } //:FUNCTION heal_us // void heal_us(int x); // Heal us a specified amount, truncating at max_health. void heal_us(int x) { /* DO NOT cause health to be updated in this routine, since this routine * is called from query_health(). The fact that the health isn't updated * doesn't matter anyway, since the effects of adding are cumulative, * and hitting the top has no side effects. Only subtractions from * health need to make sure health is updated (since not-added-yet healing * may make a difference in whether you die or not). */ if(health == 0) return; health += x; if(health > max_health) health = max_health; } //:FUNCTION reincarnate // void reincarnate(); // Makes us alive again! void reincarnate() { dead = 0; if(health < 1) { health = 1; } health_time = time(); } //:FUNCTION update_health // Correct the health if necessary void update_health() { if(!dead && time() != health_time) { /* pretend we've been healing ... */ heal_us(fuzzy_divide((time()-health_time) * heal_rate, 1000)); health_time = time(); } } //:FUNCTION query_health // varargs int query_health(string unused); // Find the current number of hitpoints of a monster varargs int query_health(string unused) { update_health(); return health; } //:FUNCTION query_max_health // int query_max_health(); // Find the maximum number of hitpoints of a monster. int query_max_health() { return max_health; } //:FUNCTION heal_all // void heal_all(); // Heal us completely. void heal_all() { set_health(query_max_health()); } int query_ghost() { return dead; } // Returns a simple choice of limb (target struck) for combat messages // Overload it for specific npcs as appropriate, so you don't hit the // hands of a bird, legs of a snake, etc string query_random_limb() { return choice( ({ "head", "torso", "arm", "leg" }) ); } //:FUNCTION badly_wounded // int badly_wounded(); // Returns 1 if we're nearing death. int badly_wounded() { return health < max_health / 5; } string diagnose() { string ret; if(query_ghost()) return "$N $vare dead. Other than that, things are going pretty well for $n.\n"; if(query_asleep()) ret = "$N $vare asleep.\n"; else if(query_stunned()) ret = "$N $vare stunned.\n"; else ret = ""; ret += diagnose_msg(query_health() * 100 / query_max_health()); return ret; }