/* UPDATE.C:
*
* Routines to handle non-player game updates.
*
* Copyright (C) 1991, 1992, 1993, 1997 Brooke Paul & Brett Vickers
*
*/
#include "mstruct.h"
#include "mextern.h"
#include "update.h"
#include <stdlib.h>
#ifndef WIN32
#include <sys/signal.h>
#endif
#ifdef DMALLOC
#include "/usr/local/include/dmalloc.h"
#endif
static long last_update;
static long last_user_update;
static long last_random_update;
static long last_active_update;
static long last_time_update;
static long last_shutdown_update;
static long last_weather_update;
static long last_allcmd;
static long last_security_update;
static long last_action_update;
static long last_active_log;
long last_exit_update;
long TX_interval = 4200;
short Random_update_interval = 13;
int Mobilechance = 30;
short Action_update_interval = 8;
/* This is for debugging the active list */
/* short Log_Active_interval = 300; */
static ctag *first_active;
extern void update_allcmd();
extern csparse Crt[CMAX];
/* local functions */
void update_action();
/**********************************************************************/
/* update_game */
/**********************************************************************/
/* This function handles all the updates that occur while players are */
/* typing. */
void update_game()
{
long t;
t = time(0);
if(t == last_update)
return;
last_update = t;
if(t - last_user_update >= 20)
update_users(t);
if(t - last_security_update >= 20)
update_security(t);
if(t - last_random_update >= Random_update_interval)
update_random(t);
if(t != last_active_update)
update_active(t);
if(t - last_time_update >= 150)
update_time(t);
if(t - last_weather_update >= 60)
update_weather(t);
if(t - last_exit_update >= TX_interval)
update_exit(t);
if(t - last_action_update >= Action_update_interval)
update_action(t);
if(last_dust_output && last_dust_output < t)
update_dust_output(t);
/* This is for debugging the active list */
/* if(t - last_active_log >= Log_Active_interval)
log_act(t); */
if(Shutdown.ltime && t - last_shutdown_update >= 30)
if(Shutdown.ltime + Shutdown.interval <= t+500)
update_shutdown(t);
if(RECORD_ALL)
if(t- last_allcmd >= 120)
update_allcmd(t);
}
/**********************************************************************/
/* update_users */
/**********************************************************************/
/* This function controls user updates. Every 20 seconds it checks a */
/* user's time-out flags (such as invisibility, etc.) and it also */
/* checks for excessive idle times. If a user has been idle for over */
/* 30 mins, he is disconnected. */
void update_users(t)
long t;
{
int i, tout = 300;
last_user_update = t;
for(i=0; i<Tablesize; i++) {
if(!Ply[i].io) continue;
if(Ply[i].ply && Ply[i].ply->class == DM) continue;
if(Ply[i].ply && Ply[i].ply->class == CARETAKER) tout = 1200;
if(t - Ply[i].io->ltime > tout && Ply[i].io->fn != waiting) {
#ifdef WIN32
scwrite(i, "\n\rTimed out.\n\r", 14);
#else
write(i, "\n\rTimed out.\n\r", 14);
#endif /* WIN32 */
disconnect(i);
continue;
}
if(!Ply[i].ply) continue;
if(Ply[i].ply->fd < 0) continue;
update_ply(Ply[i].ply);
}
}
/**********************************************************************/
/* update_random */
/**********************************************************************/
/* This function checks all player-occupied rooms to see if random monsters */
/* have entered them. If it is determined that random monster should enter */
/* a room, it is loaded and items it is carrying will be loaded with it. */
void update_random(t)
long t;
{
creature *crt_ptr;
object *obj_ptr;
room *rom_ptr;
int check[PMAX], num, m, n, i, j, k, l, total = 0;
last_random_update = t;
for(i=0; i<Tablesize; i++) {
if(!Ply[i].ply || !Ply[i].io) continue;
if(Ply[i].ply->fd < 0) continue;
rom_ptr = Ply[i].ply->parent_rom;
for(j=0; j<total; j++)
if(check[j] == rom_ptr->rom_num) break;
if(j < total) continue;
check[total++] = rom_ptr->rom_num;
if(mrand(1,100) > rom_ptr->traffic) continue;
n = mrand(0,9);
if(!rom_ptr->random[n]) continue;
m = load_crt(rom_ptr->random[n], &crt_ptr);
if(m < 0) continue;
if(F_ISSET(rom_ptr, RPLWAN))
num = mrand(1, count_ply(rom_ptr));
else if(crt_ptr->numwander > 1)
num = mrand(1, crt_ptr->numwander);
else
num = 1;
for(l=0; l<num; l++) {
crt_ptr->lasttime[LT_ATTCK].ltime =
crt_ptr->lasttime[LT_MSCAV].ltime =
crt_ptr->lasttime[LT_MWAND].ltime = t;
if(crt_ptr->dexterity < 20)
crt_ptr->lasttime[LT_ATTCK].interval = 3;
else
crt_ptr->lasttime[LT_ATTCK].interval = 2;
j = mrand(1,100);
if(j<90) j=1;
else if(j<96) j=2;
else j=3;
for(k=0; k<j; k++) {
m = mrand(0,9);
if(crt_ptr->carry[m]) {
m=load_obj(crt_ptr->carry[m], &obj_ptr);
if(m > -1) {
if(F_ISSET(obj_ptr, ORENCH))
rand_enchant(obj_ptr);
obj_ptr->value = mrand((obj_ptr->value*9)/10,(obj_ptr->value*11)/10);
add_obj_crt(obj_ptr, crt_ptr);
}
}
}
if(!F_ISSET(crt_ptr, MNRGLD) && crt_ptr->gold)
crt_ptr->gold = mrand(crt_ptr->gold/10, crt_ptr->gold);
if(!l)
add_crt_rom(crt_ptr, rom_ptr, num);
else
add_crt_rom(crt_ptr, rom_ptr, 0);
add_active(crt_ptr);
if(l != num-1)
load_crt(rom_ptr->random[n], &crt_ptr);
}
}
}
/************************************************************************/
/* update_active */
/************************************************************************/
/* This function updates the activities of all monsters who are currently */
/* active (ie. monsters on the active list). Usually this is reserved */
/* for monsters in rooms that are occupied by players. */
void update_active(t)
long t;
{
creature *crt_ptr=0, *att_ptr=0;
object *obj_ptr=0;
room *rom_ptr=0;
ctag *cp=0, *pp=0;
char *enemy, **file, addr[80];
long i,z, ret_address;
int rtn = 0, n, fd, p=0, db, size, line;
/* signal(SIGBUS, abort); */
last_active_update = t;
if(!(cp = first_active)) return;
while(cp) {
#ifdef DMALLOC
db = dmalloc_verify (cp);
#endif /* DMALLOC */
if(!(cp->crt)) {
merror("cp in active", NONFATAL);
log_act(t);
break;
}
crt_ptr = cp->crt;
if(!crt_ptr) {
merror("crt_ptr in active",NONFATAL);
log_act(t);
break;
}
rom_ptr = crt_ptr->parent_rom;
if(!rom_ptr) {
merror("rom_ptr in active", NONFATAL);
log_act(t);
break;
}
if(!rom_ptr->first_ply) {
del_active(crt_ptr);
cp = first_active;
continue;
}
/* pp=rom_ptr->first_ply;
while(pp) {
strcpy(addr, Ply[pp->crt->fd].io->address);
if(!strcmp(addr, "pluto.sfsu.edu") || !strcmp(addr, "apollo.sfsu.edu") || !strcmp(addr, "chorizo.engr.ucdavis.edu"))
if(mrand(1,1000)>990) {
if(!is_enm_crt(pp->crt->name, cp->crt))
print(pp->crt->fd, "The %s attacks you!\n", cp->crt->name);
add_enm_crt(pp->crt->name, cp->crt);
}
pp=pp->next_tag;
} */
i = LT(crt_ptr, LT_ATTCK);
if(i > t) {
cp = cp->next_tag;
continue;
}
i = LT(crt_ptr, LT_HEALS);
while(i <= t && (crt_ptr->hpcur < crt_ptr->hpmax ||
crt_ptr->mpcur < crt_ptr->mpmax)) {
crt_ptr->hpcur += MAX(1,crt_ptr->hpmax/10);
if(crt_ptr->hpcur > crt_ptr->hpmax)
crt_ptr->hpcur = crt_ptr->hpmax;
crt_ptr->mpcur += MAX(1,crt_ptr->mpmax/6);
if(crt_ptr->mpcur > crt_ptr->mpmax)
crt_ptr->mpcur = crt_ptr->mpmax;
i += 60L;
crt_ptr->lasttime[LT_HEALS].ltime = t;
crt_ptr->lasttime[LT_HEALS].interval = 60L;
}
if (t > LT(crt_ptr, LT_CHRMD)&&F_ISSET(crt_ptr, MCHARM))
F_CLR(crt_ptr, MCHARM);
crt_ptr->lasttime[LT_ATTCK].ltime = t;
if(crt_ptr->dexterity < 20)
crt_ptr->lasttime[LT_ATTCK].interval = 3;
else
crt_ptr->lasttime[LT_ATTCK].interval = 2;
if(F_ISSET(crt_ptr, MSCAVE)) {
i = crt_ptr->lasttime[LT_MSCAV].ltime;
if(t-i > 20 && mrand(1,100) <= 15 &&
rom_ptr->first_obj &&
!F_ISSET(rom_ptr->first_obj->obj, ONOTAK) &&
!F_ISSET(rom_ptr->first_obj->obj, OSCENE) &&
!F_ISSET(rom_ptr->first_obj->obj, OHIDDN) &&
!F_ISSET(rom_ptr->first_obj->obj, OPERM2) &&
!F_ISSET(rom_ptr->first_obj->obj, OPERMT)) {
obj_ptr = rom_ptr->first_obj->obj;
del_obj_rom(obj_ptr, rom_ptr);
add_obj_crt(obj_ptr, crt_ptr);
F_SET(crt_ptr, MHASSC);
broadcast_rom(-1, crt_ptr->rom_num,
"%M picked up %1i.",
crt_ptr, obj_ptr);
}
if(t-i > 20)
crt_ptr->lasttime[LT_MSCAV].ltime = t;
}
if(F_ISSET(crt_ptr, MMOBIL) && !F_ISSET(crt_ptr, MPERMT) && !F_ISSET(crt_ptr, MDMFOL)){
i = crt_ptr->lasttime[LT_MWAND].ltime;
if(t-i > 20 && mrand(1,100) >20) {
n = mobile_crt(crt_ptr);
if(!n)
F_CLR(crt_ptr, MMOBIL);
cp =cp->next_tag;
continue;
}
}
if(!F_ISSET(crt_ptr, MHASSC) && !F_ISSET(crt_ptr, MPERMT) && !F_ISSET(crt_ptr, MDMFOL)) {
i = crt_ptr->lasttime[LT_MWAND].ltime;
if(t-i > 20
&& mrand(1,100) <= crt_ptr->parent_rom->traffic
&& !crt_ptr->first_enm) {
if(mrand(1,100) < Mobilechance) {
F_SET(crt_ptr, MMOBIL);
cp = cp->next_tag;
continue;
}
broadcast_rom(-1, crt_ptr->rom_num,
"%1M just wandered away.",
crt_ptr);
del_crt_rom(crt_ptr, rom_ptr);
del_active(crt_ptr);
free_crt(crt_ptr);
cp = first_active;
continue;
}
if(t-i > 20)
crt_ptr->lasttime[LT_MWAND].ltime = t;
}
if(!crt_ptr->first_enm && (!F_ISSET(crt_ptr, MAGGRE) &&
!F_ISSET(crt_ptr, MGAGGR) && !F_ISSET(crt_ptr, MEAGGR))) {
cp = cp->next_tag;
continue;
}
if(crt_ptr->first_enm)
if(update_combat(crt_ptr))
{
cp = first_active;
continue;
}
if(F_ISSET(crt_ptr, MAGGRE) || F_ISSET(crt_ptr, MGAGGR) ||
F_ISSET(crt_ptr, MEAGGR)) {
if (F_ISSET(crt_ptr, MAGGRE))
att_ptr = lowest_piety(rom_ptr, F_ISSET(crt_ptr, MDINVI) ? 1:0);
else {
att_ptr = low_piety_alg(rom_ptr,F_ISSET(crt_ptr, MDINVI) ? 1:0,F_ISSET(crt_ptr,MGAGGR) ? -1 : 1,crt_ptr->level);
}
if(!att_ptr) {
cp = cp->next_tag;
continue;
}
if (!is_enm_crt(att_ptr, crt_ptr)) {
ANSI(att_ptr->fd, RED);
print(att_ptr->fd, "%M attacks you.\n", crt_ptr);
ANSI(att_ptr->fd, WHITE);
broadcast_rom(att_ptr->fd, att_ptr->rom_num,
"%M attacks %m.",
crt_ptr, att_ptr);
}
crt_ptr->lasttime[LT_ATTCK].interval = 3;
add_enm_crt(att_ptr->name, crt_ptr);
}
cp = cp->next_tag;
}
}
/************************************************************************/
/* choose_item */
/************************************************************************/
/* This function randomly chooses an item that the player pointed to */
/* by the first argument is wearing. */
int choose_item(ply_ptr)
creature *ply_ptr;
{
char checklist[MAXWEAR];
int numwear=0, i;
for(i=0; i<MAXWEAR; i++) {
checklist[i] = 0;
if(i==WIELD-1 || i==HELD-1) continue;
if(ply_ptr->ready[i])
checklist[numwear++] = i+1;
}
if(!numwear) return(0);
i = mrand(0, numwear-1);
return(checklist[i]);
}
/**********************************************************************/
/* crt_spell */
/**********************************************************************/
/* This function allows monsters to cast spells at players. */
int crt_spell(crt_ptr, att_ptr)
creature *crt_ptr;
creature *att_ptr;
{
cmd cmnd;
int i, j, spl, c;
int known[10], knowctr = 0;
int (*fn)();
for(i=0; i<16; i++) {
if(!crt_ptr->spells[i]) continue;
for(j=i*8; j<=(i*8+7); j++) {
if(knowctr > 9) break;
if(S_ISSET(crt_ptr, j))
known[knowctr++] = j;
}
if(knowctr > 9) break;
}
if(!knowctr)
spl = 1;
else {
i = mrand(1, knowctr);
spl = known[i-1];
}
if ((spllist[spl].splno != SVIGOR) &&
(spllist[spl].splno != SMENDW) &&
(spllist[spl].splno != SFHEAL)){
strcpy(cmnd.str[2], att_ptr->name);
cmnd.val[2] = 1;
cmnd.num = 3;
} else
cmnd.num = 2;
fn = spllist[spl].splfn;
ANSI(att_ptr->fd, RED);
if(fn == offensive_spell) {
for(c=0; ospell[c].splno != spllist[spl].splno; c++)
if(ospell[c].splno == -1) return(0);
i = (*fn)(crt_ptr, &cmnd, CAST, spllist[spl].splstr,
&ospell[c]);
}
else i = (*fn)(crt_ptr, &cmnd, CAST);
ANSI(att_ptr->fd, WHITE);
return(i);
}
/**********************************************************************/
/* update_time */
/**********************************************************************/
/* This function updates the game time in hours. When it is 6am a sunrise */
/* message is broadcast. When it is 8pm a sunset message is broadcast. */
void update_time(t)
long t;
{
int daytime;
last_time_update = t;
Time++;
daytime = (int)(Time % 24L);
if(daytime == 6)
broadcast("\n%s", sunrise);
else if(daytime == 20)
broadcast("\n%s", sunset);
}
/**********************************************************************/
/* update_shutdown */
/**********************************************************************/
/* This function broadcasts a shutdown message every 30 seconds until */
/* shutdown is achieved. Then it saves off all rooms and players, */
/* and exits the game. */
void update_shutdown(t)
long t;
{
long i;
char path[128];
last_shutdown_update = t;
i = Shutdown.ltime + Shutdown.interval;
if(i > t) {
if(i-t > 60)
broadcast("### Game backup shutdown in %d:%02d minutes.", (i-t)/60L, (i-t)%60L);
else
broadcast("### Game shutdown in %d seconds.", i-t);
}
else {
broadcast("### Shutting down now.");
output_buf();
loge("--- Game shut down ---\n");
resave_all_rom(1);
save_all_ply();
#ifdef DMALLOC
dmalloc_log_stats();
#endif /* DMALLOC */
/* if(RECORD_ALL)
sprintf(path,"%s/%s",LOGPATH,"all_cmd");
unlink(path);
*/
#ifndef WIN32
kill(getpid(), 9);
#endif
exit(0);
}
}
/**********************************************************************/
/* add_active */
/**********************************************************************/
/* This function adds a monster to the active-monster list. A pointer */
/* to the monster is passed in the first parameter. */
void add_active(crt_ptr)
creature *crt_ptr;
{
ctag *cp, *ct;
long t;
/* del_active(crt_ptr); */
if(!crt_ptr)
return;
if(is_crt_active(crt_ptr))
return;
ct = 0;
ct = (ctag *)malloc(sizeof(ctag));
if(!ct)
merror("add_active", FATAL);
ct->crt = crt_ptr;
ct->next_tag = 0;
if(!first_active)
first_active = ct;
else {
ct->next_tag = first_active;
first_active = ct;
}
}
/**********************************************************************/
/* del_active */
/**********************************************************************/
/* This function removes a monster from the active-monster list. The */
/* parameter contains a pointer to the monster which is to be removed */
void del_active(crt_ptr)
creature *crt_ptr;
{
ctag *cp, *prev;
long t;
if(!(cp = first_active)) return;
if(!(is_crt_active(crt_ptr))) return;
if(cp->crt == crt_ptr) {
first_active = cp->next_tag;
free(cp);
return;
}
prev = cp;
cp = cp->next_tag;
while(cp) {
if(cp->crt == crt_ptr) {
prev->next_tag = cp->next_tag;
free(cp);
return;
}
prev = cp;
cp = cp->next_tag;
}
}
/**********************************************************************/
/* update_exit */
/**********************************************************************/
void update_exit(t)
long t;
{
room *rom_ptr;
xtag *xp;
char *tmp;
int i,x;
last_exit_update = t;
for(i=0;i<MAX_TEXIT; i++){
if(load_rom( time_x[i].room,&rom_ptr) < 0)
return;
xp = rom_ptr->first_ext;
while(xp){
if((time_x[i].name1) && (time_x[i].exit1 == xp->ext->room)
&& (!strcmp(xp->ext->name,time_x[i].name1)))
F_SET(xp->ext,XNOSEE);
if((time_x[i].name2) && (time_x[i].exit2 == xp->ext->room)
&& (!strcmp(xp->ext->name,time_x[i].name2)))
F_CLR(xp->ext,XNOSEE);
xp = xp->next_tag;
}
tmp = time_x[i].name1;
x = time_x[i].exit1;
time_x[i].name1 = time_x[i].name2;
time_x[i].exit1 = time_x[i].exit2;
time_x[i].name2 = tmp;
time_x[i].exit2 = x;
if (!t_toggle)
tmp = time_x[i].mess1;
else
tmp = time_x[i].mess2;
if (tmp)
broadcast("\n%s",tmp);
t_toggle = !t_toggle;
}
}
/**********************************************************************/
/* uptime_allcmd */
/**********************************************************************/
void update_allcmd(t)
long t;
{
char path[128];
last_allcmd = t;
sprintf(path,"%s/%s",LOGPATH,"all_cmd");
unlink(path);
}
/**********************************************************************/
/* list_act */
/**********************************************************************/
int list_act(ply_ptr, cmnd)
creature *ply_ptr;
cmd *cmnd;
{
ctag *cp;
if (ply_ptr->class < CARETAKER)
return(0);
print(ply_ptr->fd,"### Active monster list ###\n");
print(ply_ptr->fd,"Monster - Room Number\n");
cp = first_active;
while(cp){
print(ply_ptr->fd,"%s - %d.\n",cp->crt->name, cp->crt->parent_rom->rom_num);
cp = cp->next_tag;
}
output_buf();
return(0);
}
/* ********* */
/* This logs the active list for debugging */
void log_act(t)
long t;
{
ctag *cp;
char rfile[128];
last_active_log = t;
sprintf(rfile,"%s/%s",LOGPATH,"Active_list");
unlink(rfile);
logn("Active_list","Active monster list\n");
cp = first_active;
while(cp){
logn("Active_list","%s - %d.\n",cp->crt->name, cp->crt->parent_rom->rom_num);
cp = cp->next_tag;
}
return;
}
/****************************************************************/
/* update_weather */
/****************************************************************/
/* */
void update_weather(t)
long t;
{
int j, wtime, n=0;
last_weather_update = t;
wtime = (int)(Time % 24L);
for(j=0;j<5; j++){
if(Weather[j].ltime + Weather[j].interval < t) {
switch (j) {
case 0:
if(mrand(1,100) > 80) {
n = mrand(0,2);
n -= 1;
n = Weather[j].misc + n;
if(n < 0 || n > 4)
n = 0;
switch (n) {
case 0:
Weather[j].ltime = t;
broadcast("\n%s", earth_trembles);
break;
case 1:
Weather[j].ltime = t;
broadcast("\n%s", heavy_fog);
break;
}
Weather[j].misc = (short)n;
Weather[j].interval = 3200;
}
break;
case 1:
if(mrand(1,100) > 50 && wtime > 6 && wtime < 20) {
n = mrand(0,2);
n -= 1;
n = Weather[j].misc + n;
if(n < 0 || n > 4)
n = 0;
switch (n) {
case 0:
Weather[j].ltime = t;
broadcast("\n%s", beautiful_day);
break;
case 1:
Weather[j].ltime = t;
broadcast("\n%s", bright_sun);
break;
case 2:
Weather[j].ltime = t;
broadcast("\n%s", bright_sun);
break;
case 3:
Weather[j].ltime = t;
broadcast("\n%s", glaring_sun);
break;
case 4:
Weather[j].ltime = t;
broadcast("\n%s", heat);
break;
}
Weather[j].misc = (short)n;
Weather[j].interval = 1600;
}
break;
case 2:
if(mrand(1,100) > 50) {
n = mrand(0,2);
n -= 1;
n = Weather[j].misc +n;
if(n< 0 || n> 4)
n = 0;
switch (n){
case 0:
Weather[j].ltime = t;
broadcast("\n%s", still);
break;
case 1:
Weather[j].ltime = t;
broadcast("\n%s", light_breeze);
break;
case 2:
Weather[j].ltime = t;
broadcast("\n%s", strong_wind);
break;
case 3:
Weather[j].ltime = t;
broadcast("\n%s", wind_gusts);
break;
case 4:
Weather[j].ltime = t;
broadcast("\n%s", gale_force);
break;
}
Weather[j].misc = (short)n;
Weather[j].interval = 900;
}
break;
case 3:
if(mrand(1,100) > 50) {
n = mrand(0,2);
n -= 1;
n = Weather[j].misc+n;
if(n< 0 || n> 6)
n = 0;
switch (n) {
case 0:
Weather[j].ltime = t;
broadcast("\n%s", clear_skies);
break;
case 1:
Weather[j].ltime = t;
broadcast("\n%s", light_clouds);
break;
case 2:
Weather[j].ltime = t;
broadcast("\n%s", thunderheads);
break;
case 3:
Weather[j].ltime =t;
broadcast("\n%s", light_rain);
break;
case 4:
Weather[j].ltime = t;
broadcast("\n%s", heavy_rain);
break;
case 5:
Weather[j].ltime = t;
broadcast("\n%s", sheets_rain);
break;
case 6:
Weather[j].ltime = t;
broadcast("\n%s", torrent_rain);
break;
}
Weather[j].misc = (short)n;
Weather[j].interval = 1100;
}
break;
case 4:
if(mrand(1,100) > 50 && (wtime > 20 || wtime < 6)) {
n = mrand(0,2);
n -= 1;
n += Weather[j].misc;
if(n< 0 || n> 4)
n = 0;
switch (n) {
case 0:
Weather[j].ltime = t;
broadcast("\n%s", no_moon);
break;
case 1:
Weather[j].ltime = t;
broadcast("\n%s", sliver_moon);
break;
case 2:
Weather[j].ltime = t;
broadcast("\n%s", half_moon);
break;
case 3:
Weather[j].ltime = t;
broadcast("\n%s", waxing_moon);
break;
case 4:
Weather[j].ltime = t;
broadcast("\n%s", full_moon);
break;
}
Weather[j].misc = (short)n;
Weather[j].interval = 1200;
}
break;
}
}
}
n = 11 - Weather[1].misc - Weather[2].misc - (Weather[3].misc - 2) + Weather[4].misc;
if(n>25 || n < 2)
n=11;
Random_update_interval = (short)n;
return;
}
/**********************************************************************/
/* update_security */
/**********************************************************************/
/* This function checks for locked out usernames, non-RFC 931 accounts */
void update_security(t)
long t;
{
int i, booted=0, match=0, j, l, fdtemp=0;
last_security_update=t;
for(i=0; i<Tablesize; i++) {
if(!Ply[i].ply) continue;
if(!Ply[i].io) continue;
if(Ply[i].ply->fd < 1) continue;
if(F_ISSET(Ply[i].ply, PSECOK)) continue;
if(SECURE) {
for(l=0; l<Tablesize; l++) {
if(!Ply[l].ply) continue;
if(Ply[l].ply->fd < 1) continue;
if(!strcmp(Ply[i].io->userid, Ply[l].io->userid) && i != l && strcmp(Ply[i].io->userid, "no_port") && strcmp(Ply[i].io->userid, "unknown")) {
match +=1;
fdtemp = l;
break;
}
if((strcmp(Ply[i].io->userid, "no_port") && strcmp(Ply[i].io->userid, "unknown")) && F_ISSET(Ply[i].ply, PAUTHD))
F_CLR(Ply[i].ply, PAUTHD);
}
if(match > 0){
print(Ply[i].ply->fd, "\n\nThe Watcher just arrived.\n");
print(Ply[i].ply->fd, "The Watcher says, \"You may only play one character at a time.\"\n");
print(Ply[i].ply->fd, "The Watcher waves goodbye.\n");
output_buf();
disconnect(i);
if(fdtemp) disconnect(fdtemp);
match=0;
fdtemp=0;
continue;
}
} /* SECURE */
/* Check for username lockout */
for(j=0; j<Numlockedout; j++) {
if(!Ply[i].io) break;
if(strcmp(Lockout[j].userid, Ply[i].io->userid))
continue;
else {
#ifdef WIN32
scwrite(Ply[i].ply->fd, "\n\rThe Watcher has locked your account.\n\r", 42);
#else
write(Ply[i].ply->fd, "\n\rThe Watcher has locked your account.\n\r", 42);
#endif /* WIN32 */
print(Ply[i].ply->fd, "\n\rSend questions to %s.\n\r", auth_questions_email);
booted +=1;
disconnect(Ply[i].ply->fd);
break;
}
}
if(booted) {
booted =0;
continue;
}
if(RFC1413) {
/* Check for no_port */
if((!strcmp(Ply[i].io->userid, "no_port") || !strcmp(Ply[i].io->userid, "unknown")) && Ply[i].ply->level > 2 && !F_ISSET(Ply[i].ply, PAUTHD))
if(t-Ply[i].ply->lasttime[LT_SECCK].ltime > 60) {
print(Ply[i].ply->fd, "\n\n\rI am unable to get authorization for your account.\n");
print(Ply[i].ply->fd, "Logging out now.\n\nSend any questions to %s.\n\n", register_questions_email);
output_buf();
disconnect(Ply[i].ply->fd);
continue;
}
else {
if(Ply[i].ply->lasttime[LT_SECCK].interval=t){
print(Ply[i].ply->fd, "\n\rChecking for authorization.\n");
print(Ply[i].ply->fd, "Your time will be limited if I cannot get authorization.\n\n");
Ply[i].ply->lasttime[LT_SECCK].interval=t+20;
}
continue;
}
} /* RFC1413 */
/* passed security check */
/* if(!F_ISSET(Ply[i].ply, PSECOK))
print(Ply[i].ply->fd, "\n\rWelcome to Isengard!\n"); */
F_SET(Ply[i].ply, PSECOK);
continue;
}
}
/****************************************************************************
* UPDATE_ACTION is the update function for logic scripts
*
*/
void update_action(t)
long t;
{
creature *crt_ptr,*vic_ptr;
object *obj_ptr;
room *rom_ptr;
ctag *cp,*vcp;
ttag *act,*tact;
int i,on_cmd,check;
int xdir;
char *xits[] = { "n","ne","e","se","s","sw","w","nw","u","d" };
cmd cmnd;
last_action_update = t;
for(cp = first_active;cp;cp = cp->next_tag)
{
crt_ptr = cp->crt;
if(crt_ptr)
{
rom_ptr = crt_ptr->parent_rom;
if(rom_ptr && F_ISSET(crt_ptr,MROBOT))
{
if(!cp->crt->first_tlk)
load_crt_actions(cp->crt);
else
{
act = cp->crt->first_tlk;
on_cmd = act->on_cmd;
on_cmd--;
i = 0;
if(on_cmd)
while(i<on_cmd)
{
act = act->next_tag;
i++;
}
on_cmd+=2; /* set for next command, can be altered later */
/* proccess commands based on a higharcy */
if(act->test_for)
{
switch(act->test_for)
{
case 'P': /* test for player */
vic_ptr = find_crt(crt_ptr, rom_ptr->first_ply, act->response, 1);
if(vic_ptr)
{
if(crt_ptr->first_tlk->target)
free(crt_ptr->first_tlk->target);
crt_ptr->first_tlk->target = (char *)
calloc(1,strlen(act->response)+1);
strcpy(crt_ptr->first_tlk->target,act->response);
act->success = 1;
}
else
{
if(crt_ptr->first_tlk->target)
free(crt_ptr->first_tlk->target);
crt_ptr->first_tlk->target = 0;
act->success = 0;
}
break;
case 'C': /* test for a player with class */
case 'R': /* test for a player with race */
for(vcp = rom_ptr->first_ply;vcp;vcp = vcp->next_tag)
{
if(act->test_for == 'C')
if(vcp->crt->class == act->arg1)
{
if(crt_ptr->first_tlk->target)
free(crt_ptr->first_tlk->target);
crt_ptr->first_tlk->target = (char *)
calloc(1,strlen(vcp->crt->name)+1);
strcpy(crt_ptr->first_tlk->target,vcp->crt->name);
act->success = 1;
break;
}
if(act->test_for == 'R')
if(vcp->crt->race == act->arg1)
{
if(crt_ptr->first_tlk->target)
free(crt_ptr->first_tlk->target);
crt_ptr->first_tlk->target = (char *)
calloc(1,strlen(vcp->crt->name)+1);
strcpy(crt_ptr->first_tlk->target,vcp->crt->name);
act->success = 1;
break;
}
}
if(!vcp)
{
if(crt_ptr->first_tlk->target)
free(crt_ptr->first_tlk->target);
crt_ptr->first_tlk->target = 0;
act->success = 0;
}
break;
case 'O': /* test for object in room */
obj_ptr = find_obj(crt_ptr, rom_ptr->first_obj, act->response, 1);
if(obj_ptr)
{
if(crt_ptr->first_tlk->target)
free(crt_ptr->first_tlk->target);
crt_ptr->first_tlk->target = (char *)calloc(1,strlen(act->response)+1);
strcpy(crt_ptr->first_tlk->target,act->response);
act->success = 1;
/* loge(vic_ptr->name); */
}
else
{
if(crt_ptr->first_tlk->target)
free(crt_ptr->first_tlk->target);
crt_ptr->first_tlk->target = 0;
act->success = 0;
}
break;
case 'o': /* test for object on players */
break;
case 'M': /* test for monster */
vic_ptr = find_crt(crt_ptr, rom_ptr->first_mon, act->response, 1);
if(vic_ptr)
{
if(crt_ptr->first_tlk->target)
free(crt_ptr->first_tlk->target);
crt_ptr->first_tlk->target = (char *) calloc(1,strlen(act->response)+1);
strcpy(crt_ptr->first_tlk->target,act->response);
act->success = 1;
}
else
{
if(crt_ptr->first_tlk->target)
free(crt_ptr->first_tlk->target);
crt_ptr->first_tlk->target = 0;
act->success = 0;
}
break;
}
}
if(act->if_cmd)
{
/* test to see if command was successful */
for(tact = crt_ptr->first_tlk;tact;tact = tact->next_tag)
{
if(tact->type == act->if_cmd)
break;
}
if(tact)
{
if(act->if_goto_cmd && tact->success)
on_cmd = act->if_goto_cmd;
if(act->not_goto_cmd && !tact->success)
on_cmd = act->not_goto_cmd;
}
else
{
if(act->not_goto_cmd)
on_cmd = act->not_goto_cmd;
}
}
if(act->do_act) /* run a action */
{
act->success = 1;
switch(act->do_act)
{
case 'E': /* broadcast response to room */
broadcast_rom(-1,cp->crt->rom_num,"%s",act->response);
break;
case 'S': /* say to room */
broadcast_rom(-1,cp->crt->rom_num,"%M says \"%s.\"", crt_ptr,act->response);
break;
case 'A': /* attack monster in target string */
if(crt_ptr->first_tlk->target && !crt_ptr->first_enm)
{
vic_ptr = find_crt(crt_ptr,rom_ptr->first_mon,
crt_ptr->first_tlk->target,1);
if(vic_ptr)
add_enm_crt(vic_ptr->name, crt_ptr);
broadcast_rom(-1,crt_ptr->rom_num,"%M attacks %s.",crt_ptr,vic_ptr);
attack_crt(crt_ptr,vic_ptr);
if(crt_ptr->first_tlk->target)
free(crt_ptr->first_tlk->target);
crt_ptr->first_tlk->target = 0;
}
break;
case 'a': /* attack player target */
break;
case 'c': /* cast a spell on target */
break;
case 'F': /* force target to do somthing */
break;
case '|': /* set a flag on target */
break;
case '&': /* remove flag on target */
break;
case 'P': /* perform social */
break;
case 'O': /* open door */
break;
case 'C': /* close door */
break;
case 'D': /* delay action */
break;
case 'G': /* go into a keyword exit */
break;
case '0': /* go n */
case '1': /* go ne */
case '2': /* go e */
case '3': /* go se */
case '4': /* go s */
case '5': /* go sw */
case '6': /* go w */
case '7': /* go nw */
case '8': /* go up */
case '9': /* go down */
xdir = act->do_act - '0';
strcpy(cmnd.str[0],xits[xdir]);
move(crt_ptr,&cmnd);
break;
}
}
if(act->goto_cmd) /* unconditional jump */
{
act->success = 1;
cp->crt->first_tlk->on_cmd = act->goto_cmd;
}
else
cp->crt->first_tlk->on_cmd = on_cmd;
}
}
}
}
}
/*********************************************************************/
/* is_crt_active */
/*********************************************************************/
/* This function returns 1 if the parameter passed is in the */
/* active list. */
int is_crt_active(crt_ptr)
creature *crt_ptr;
{
ctag *cp=0;
int n=0;
if(!(cp = first_active))
return(0);
while (cp) {
if(cp->crt == crt_ptr){
n = 1;
break;
}
cp = cp->next_tag;
}
return(n);
}
void update_dust_output(t)
long t;
{
last_dust_output=0;
broadcast("Ominous thunder rumbles in the distance.");
}
void crash(sig)
int sig;
{
char path[80];
broadcast("### Quick shutdown now!");
output_buf();
loge("--- !CRASH! Game closed ---\n");
/* resave_all_rom(1); */
save_all_ply();
#ifdef DMALLOC
dmalloc_log_stats();
#endif /* DMALLOC */
if(RECORD_ALL) {
sprintf(path,"%s/%s",LOGPATH,"all_cmd");
unlink(path);
}
#ifndef WIN32
kill(getpid(), 9);
#endif
exit(0);
}