/* -*- LPC -*- */
/*
* $Locker: $
* $Id: fairy_godmothers.c,v 1.14 2002/09/02 11:39:59 taffyd Exp $
* $Log: fairy_godmothers.c,v $
* Revision 1.14 2002/09/02 11:39:59 taffyd
* Changed non-existant set_social_points() method to new set_sp().
*
* Revision 1.13 2002/08/03 22:54:56 tilly
* Changed it to query the player's start location instead of being hard coded for the Drum or CWC.
*
* Revision 1.12 2002/02/20 10:42:53 taffyd
* Temporary tweak for Cwc.
*
* Revision 1.11 2002/01/25 13:24:12 tilly
* Added a call_out to move the godmother to the rubbish room, because she vanished before moving the player and saying all her lines. Also added an exit message for when she vanishes.
*
* Revision 1.10 2001/12/27 01:06:48 drakkos
* Added some logging and a playerinfo entry for when using the godmother costs a life.
*
* Revision 1.9 2001/03/24 00:08:47 ceres
* Fixed death cost & GMs not speaking when they arrive.
*
* Revision 1.8 2001/03/09 21:55:47 ceres
* Added entry message for godmothers
*
* Revision 1.6 2000/06/27 00:17:43 pinkfish
* change to use the config.h file.
*
* Revision 1.5 2000/04/08 01:33:06 pinkfish
* Fix up some errors in the godmother handler.
*
* Revision 1.4 1999/05/21 18:22:02 rywfol
* Fixed bug/typo which prevented the "attacked godmother"
* property from doing anything..
*
* Revision 1.3 1998/06/12 23:29:20 presto
* Fixed typo
*
* Revision 1.2 1998/05/02 16:44:53 presto
* Fixed typo, it's --> its
*
* Revision 1.1 1998/01/06 05:03:33 ceres
* Initial revision
*
*/
/**
* Keep track of all the fairy godmothers. Make sure they don't do any
* thing naughty. This also controls the costs for the godmother
* service.
* @author Pinkfish
*/
#include <panic.h>
#include <config.h>
#include <playerinfo.h>
#include <cwc.h>
#define HARRY_SHADOW "/std/shadows/misc/harry_shadow"
object* _panicers;
object* _godmothers;
object* _queue;
#define FREE_NAME "free trip"
#define THRESHOLD 50
#define DAY (60*60*24)
/* Prototypes */
public void continue_panicing(string str, object panicer);
private object startup_godmother(object ob);
private void finish_with_person(object ob, int ok);
/* Functions */
void create() {
_panicers = ({ });
_godmothers = allocate(NUM_GODMOTHERS);
_queue = ({ });
} /* setup() */
/**
* Return an array of all the godmothers. This is the current set of
* used godmothers.
* @return an array of objects of godmothers
*/
object *query_godmothers() { return copy(_godmothers); }
/**
* Check to see if there are any free godmothers. Are you being
* served?
* @return 1 if there is a free one, 0 if there is not
*/
int free_godmothers() {
int i;
for (i=0;i<sizeof(_godmothers);i++) {
if (!_godmothers[i]) {
return 1;
}
}
return 0;
} /* free_godmothers() */
/**
* This method handles a player panicing.
* <p>
* This is the fairy godmother controller for panicing.
* <p>
* When someone panics it calls on this object to help fix them
* up.
* @param panicer the person panicing
* @return 0 if they were unmable to panic, 1 if they were
*/
int do_startup(object panicer) {
if (environment(panicer) &&
environment(panicer)->query_property("no godmother")) {
notify_fail(environment(panicer)->query_property("no godmother"));
return 0;
}
if (panicer->query_property("attacked godmother") &&
(panicer->query_property("attacked godmother") + DAY * 10) > time())
{
notify_fail("You attacked a godmother! No help for you!\n");
return 0;
}
if (sizeof(panicer->query_attacker_list())) {
notify_fail("You cannot use a godmother whilst you are in a fight.\n");
return 0;
}
panicer->remove_property("attacked godmother");
_panicers -= ({ 0 });
if (member_array(panicer, _panicers) != -1 ||
member_array(panicer, _queue) != -1)
{
notify_fail("You are already requesting assistance. Be patient.\n");
return 0;
}
if (!panicer) {
panicer = this_player();
}
if (panicer->query_level() < 10 ||
!arrayp(environment(panicer)->query_exits()) ||
!sizeof(environment(panicer)->query_exits()) ||
!environment(panicer))
{
write("You feel help is on its way.\n");
panicer->add_property("godmother", FREE_NAME);
continue_panicing("y", panicer);
}
else {
panicer->remove_property("godmother");
if (panicer->query_level() < 50) {
int max_gp;
max_gp = panicer->query_max_gp();
if (panicer->query_gp() < max_gp / 3) {
notify_fail("You do not have enough guild points to summon "
"a godmother. You need at least " +
(max_gp / 3) + ".\n");
return 0;
}
write("This will cost you all of your current guild points and "
"social points, and leave you feeling a little weak. "
"Do you wish to continue? ");
input_to("continue_panicing", 0, panicer);
}
else {
if (panicer->query_max_deaths() <= panicer->query_deaths()) {
notify_fail("You do not have a life to spend on a godmother.\n");
return 0;
}
write("This will cost you a life, do you wish to continue? ");
input_to("continue_panicing", 0, panicer);
}
}
return 1;
} /* do_startup() */
/** @ignore yes */
private void do_check_queue() {
_queue -= ({ 0 });
if (sizeof(_queue)) {
if (startup_godmother(_queue[0])) {
_queue = _queue[1..];
}
}
} /* do_check_queue() */
/** @ignore yes */
private void setup_harrass_callout() {
int i;
int check_queue;
int waiting;
int max_wait;
for (i = 0; i < sizeof(_godmothers); i++) {
if (_godmothers[i]) {
waiting = _godmothers[i]->query_waiting();
if (waiting > FIRST_WAIT_TIME && environment(_godmothers[i])) {
_godmothers[i]->hurry_up();
}
if (!environment(_godmothers[i])) {
_godmothers[i]->dest_me();
check_queue = 1;
}
if (waiting > max_wait) {
max_wait = waiting;
}
}
}
if (max_wait < FIRST_WAIT_TIME) {
call_out("do_hurry_up", FIRST_WAIT_TIME-max_wait+2);
}
if (check_queue) {
do_check_queue();
}
} /* setup_harrass_callout() */
/** @ignore yes */
void continue_panicing(string str, object panicer) {
str = lower_case(str);
if (!str || str == "" || (str[0] != 'y' && str[0] != 'n')) {
if (panicer->query_level() < 100) {
write("This will cost you all of your current guild points and "
"social points and leave you feeling a little weak. "
"Do you wish to continue? ");
input_to("continue_panicing", 0, panicer);
return ;
}
else {
write("This will cost you a life, do you wish to continue? ");
input_to("continue_panicing", 0, panicer);
return ;
}
}
if (str[0] == 'n') {
write("Ok. They do not show up to help you. Good luck.\n");
return ;
}
if (!startup_godmother(panicer)) {
write("You hope a godmother will turn up sometime soon.\n");
_queue += ({ panicer });
setup_harrass_callout();
}
} /* continue_panicing() */
void do_panic_callout(object godmother, object ob) {
godmother->do_panic(ob);
}
private object startup_godmother(object ob) {
object godmother;
int i, num;
/* Which fairy godmother do you get? */
/* Only done 2 so far... */
i = random(NUM_GODMOTHERS);
if (_godmothers[i]) {
for (num = 1; num < NUM_GODMOTHERS; num++) {
i = (i + 1) % NUM_GODMOTHERS;
if (!_godmothers[i]) break;
}
}
/* See if they're all busy... */
if (num == NUM_GODMOTHERS)
return 0;
switch (i) {
case 0:
godmother = clone_object(GODMOTHER_DIR + "granny");
break;
case 1:
godmother = clone_object(GODMOTHER_DIR + "magrat");
break;
default:
write("Something is hosed. Please file a bug report.\n");
break;
}
_godmothers[i] = godmother;
godmother->move(environment(ob), "As if by magic $N appears.", "");
call_out("do_panic_callout", 1, godmother, ob);
_panicers += ({ ob });
return godmother;
} /* startup_godmother() */
/**
* Called by the godmother when the person has completed their
* paniced transaction.
* @param person the person who paniced
* @param ok did they complete it ok?
*/
void finish_panic(object person, int ok) {
int i;
if (person) {
finish_with_person(person, ok);
}
_panicers -= ({ person });
for (i = 0; i < sizeof(_godmothers); i++) {
if (_godmothers[i] == previous_object()) {
call_out("do_move", 10, _godmothers[i] );
break;
}
}
do_check_queue();
if (!sizeof(_queue)) {
remove_call_out("do_hurry_up");
}
} /* finish_panic() */
void do_move (object fairy) {
fairy->move("/room/rubbish", "",
"With a quick flick of her wand, the fairy godmother is gone.");
fairy = 0;
} /* do_move */
private void finish_with_person(object person, int ok) {
if (member_array(person, _panicers) == -1) {
log_file("GODMOTHER_ERROR", "person == %O, godmother == %s\n", person, previous_object()->query_short());
write("Consistancy error, they never paniced.\n");
return ;
}
if (ok) {
if (person->query_property("godmother") == FREE_NAME) {
}
else if (person->query_level() < THRESHOLD) {
person->adjust_tmp_con(-2);
person->set_gp(0);
person->set_sp(0);
}
else if (person->query_level() >= THRESHOLD &&
person->query_max_deaths() > person->query_deaths()) {
PLAYERINFO_HANDLER->add_entry(person,
person->query_name(), "misc", "Lost a life to the Godmother");
log_file("GODMOTHER_DEATH", "%s: %s lost a life to the Godmother\n",
ctime(time()), person->query_name());
person->adjust_deaths(1);
}
call_out(function(object person) {
string destination;
destination = person->query_nationality()->query_default_start_location();
person->move_with_look(destination,
"$N appears out of nowhere.",
"$N disappears with a pop.");
if (person->query_ghost()) {
person->remove_ghost();
clone_object(HARRY_SHADOW)->setup_shadow(person,
"a fairy godmother" );
}
}, 2, person);
}
person->remove_property("godmother");
} /* finish_with_person() */
/**
* Give the players a nudge if they are taking to long.
*/
void do_hurry_up() {
int i;
int waiting;
int max_wait;
if (!sizeof(_queue)) {
return ;
}
for (i = 0; i < sizeof(_godmothers); i++) {
if (_godmothers[i]) {
if (!environment(_godmothers[i])) {
_godmothers[i]->dest_me();
_godmothers[i] = 0;
}
else {
waiting = _godmothers[i]->query_waiting();
if (waiting > FIRST_WAIT_TIME) {
if (waiting > FINISH_WAIT_TIME) {
_godmothers[i]->finish_up();
} else {
_godmothers[i]->hurry_up();
}
}
if (waiting > max_wait) {
max_wait = waiting;
}
}
}
}
if (max_wait > 0) {
if (FINISH_WAIT_TIME - max_wait < 10) {
call_out("do_hurry_up", 10);
} else {
call_out("do_hurry_up", FINISH_WAIT_TIME-max_wait);
}
}
} /* do_hurry_up() */
/** @ignore yes */
void dest_me() {
int i;
for (i = 0; i < sizeof(_godmothers); i++) {
if (_godmothers[i]) {
_godmothers[i]->dest_me();
}
}
destruct(this_object());
} /* dest_me() */