/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* Ground ZERO improvements copyright pending 1994, 1995 by James Hilke *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "ground0.h"
/* command procedures needed */
DECLARE_DO_FUN(do_quit );
/*
* Local functions.
*/
int hit_gain args( ( CHAR_DATA *ch ) );
int mana_gain args( ( CHAR_DATA *ch ) );
int move_gain args( ( CHAR_DATA *ch ) );
void mobile_update args( ( void ) );
void weather_update args( ( void ) );
void char_update args( ( void ) );
void obj_update args( ( void ) );
void aggr_update args( ( void ) );
/* used for saving */
int save_number = 0;
int tick_counter = 0;
/*
* Regeneration stuff.
*/
int hit_gain( CHAR_DATA *ch )
{
int gain;
int number;
gain = number_range (125, 325);
switch ( ch->position )
{
case POS_SLEEPING: gain *= 2; break;
}
return UMIN(gain, ch->max_hit - ch->hit);
}
/*
* Update all chars, including mobs.
*/
void char_update( void )
{
CHAR_DATA *ch;
CHAR_DATA *ch_next;
/* update save counter */
save_number++;
if (save_number > 29)
save_number = 0;
for ( ch = char_list; ch != NULL; ch = ch_next )
{
ch_next = ch->next;
if (ch->ld_timer == 1)
{
ch->last_hit_by = NULL;
char_death (ch);
}
if (ch->ld_timer)
ch->ld_timer--;
if (!number_range (0, 5) && IS_SET (ch->affected_by, AFF_BLIND))
{
REMOVE_BIT (ch->affected_by, AFF_BLIND);
send_to_char ("You can see again!\n\r", ch);
}
if (!number_range (0, 2) && IS_SET (ch->affected_by, AFF_DAZE))
{
REMOVE_BIT (ch->affected_by, AFF_DAZE);
send_to_char ("You are no longer dazed!\n\r", ch);
}
if ( ch->position >= POS_STUNNED )
{
if ( ch->hit < ch->max_hit )
ch->hit += hit_gain(ch);
else
ch->hit = ch->max_hit;
}
if ( ch->position == POS_STUNNED )
update_pos( ch );
if ( !IS_NPC(ch) && !ch->trust)
if (IS_IMMORTAL(ch))
ch->timer = 0;
ch->donate_num = UMAX (0, ch->donate_num - 2);
ch->chan_delay = UMAX(0, ch->chan_delay - 4*PULSE_PER_SECOND);
}
/*
* Autosave.
* Check that these chars still exist.
*/
for ( ch = char_list; ch != NULL; ch = ch_next )
{
ch_next = ch->next;
if (ch->desc != NULL && ch->desc->descriptor % 30 == save_number)
save_char_obj(ch);
}
return;
}
/*
* Update all objs.
* This function is performance sensitive.
*/
void obj_update( void )
{
OBJ_DATA *obj;
OBJ_DATA *obj_next;
AFFECT_DATA *paf, *paf_next;
CHAR_DATA *all_chars;
for ( obj = object_list; obj != NULL; obj = obj_next )
{
CHAR_DATA *rch;
char *message;
char buf[MAX_STRING_LENGTH];
DESCRIPTOR_DATA *d;
obj_next = obj->next;
if (obj->arrival_time >= 0)
{
obj->arrival_time--;
if (obj->arrival_time == -1)
{
ROOM_DATA *temp_room;
if (!obj->in_room)
sbug ("obj_update: object not in room");
obj_from_room (obj);
temp_room = obj->destination;
obj->destination = NULL;
obj_to_room (obj, temp_room);
if (obj->in_room->people)
{
act ("$p lands at your feet.", obj->in_room->people,
obj, NULL, TO_ROOM);
act ("$p lands at your feet.", obj->in_room->people,
obj, NULL, TO_CHAR);
}
if (IS_SET (obj->general_flags, GEN_EXTRACT_ON_IMPACT))
bang_obj (obj, 0);
}
}
/* for clarity, this means that we either have a timer of -1 or 0
(a stopped timer) from the first half of the clause, or we have a
timer that is positive int after subtracting 1 from it, the else
clause means the timer must have just expired */
if ( obj->timer <= 0 || --obj->timer > 0 )
{
if (obj->carried_by && obj->timer > 0)
if (IS_SET (obj->extract_flags, EXTRACT_BURN_ON_EXTRACT))
act ("$p burns quietly in your hand.", obj->carried_by, obj,
NULL, TO_CHAR);
else
act ("$p ticks very quietly.", obj->carried_by, obj, NULL,
TO_CHAR);
if (IS_SET (obj->general_flags, GEN_BURNS_ROOM))
if (obj->in_room && obj->in_room->people)
burn_obj (obj);
continue;
}
else
{
if (obj->arrival_time >= 0)
extract_obj (obj, 0);
else
{
if (obj->extract_flags)
bang_obj (obj, 0);
else
if (IS_SET (obj->general_flags, GEN_BURNS_ROOM))
{
if (obj->in_room->people)
{
act ("$p burns down and dies leaving nothing but "
"ashes.", obj->in_room->people, obj, NULL,
TO_CHAR);
act ("$p burns down and dies leaving nothing but "
"ashes.", obj->in_room->people, obj, NULL,
TO_ROOM);
}
extract_obj (obj, 1);
}
else
if (IS_SET (obj->general_flags, GEN_DARKS_ROOM))
{
if (obj->in_room->people)
{
act ("This room is no longer dark.",
obj->in_room->people, obj, NULL, TO_CHAR);
act ("This room is no longer dark.",
obj->in_room->people, obj, NULL, TO_ROOM);
}
extract_obj (obj, 1);
}
}
}
}
}
void tick_stuff (int imm_generated)
{
static int pulse_point = PULSE_TICK;
char buf[100];
CHAR_DATA *all_chars;
int count;
if ((--pulse_point > 0) && !imm_generated)
return;
sprintf(buf,"TICK %d\n\r", tick_counter);
log_string(buf);
tick_counter++;
if (!teleport_time)
{
if (!number_range (0, 99))
{
for (all_chars = char_list; all_chars;
all_chars = all_chars->next)
send_to_char ("A scratchy voice comes in over your comm "
"badge '`tRedeployment systems are\n\r"
"operational for the moment, but may go "
"offline at any second. Should you\n\rneed "
"redeployment in the near future, please do "
"so now.``'\n\r", all_chars);
teleport_time = 1;
}
}
else
{
if (!number_range (0, 11))
{
for (all_chars = char_list; all_chars;
all_chars = all_chars->next)
send_to_char ("A scratchy voice comes in over your comm "
"badge '`tTransportation systems have\n\rjust "
"gone off line. Redeployment services are "
"temporarily unavailable.``'\n\r", all_chars);
teleport_time =0;
}
}
pulse_point = PULSE_TICK;
char_update ( );
}
/*
* Handle all kinds of updates.
* Called once per pulse from game loop.
* Random times to defeat tick-timing clients and players.
*/
void update_handler()
{
static int pulse_violence = PULSE_VIOLENCE;
static int pulse_objects = PULSE_OBJECTS;
static int pulse_save = PULSE_SAVE;
tick_stuff (0);
if ( --pulse_violence <= 0 )
{
pulse_violence = PULSE_VIOLENCE;
violence_update ( );
}
if ( --pulse_objects <= 0 )
{
pulse_objects = PULSE_OBJECTS;
obj_update ( );
}
if ( --pulse_save <= 0 )
{
pulse_save = PULSE_SAVE;
do_save_all (NULL, "");
}
/* get rid of dead folk */
while (extract_list)
{
CHAR_DATA *ch;
ch = extract_list;
extract_list = extract_list->next_extract;
extract_char (ch, TRUE);
}
tail_chain( );
}