/* MAKE SURE TO JAVA_REMOVE_FROM_FIELD to everyone */ #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "emlen.h" #ifndef WINDOWS #include <sys/time.h> #include <dirent.h> #include <sys/errno.h> #include <netinet/in.h> #include <signal.h> #include <sys/types.h> #endif COMBAT_FIELD *field_list=NULL; COMBAT_FIELD *free_field_list=NULL; bool closeto=FALSE; #define FIELD_TICK_WAIT 5 bool remove_from_combat_field(CHAR_DATA *ch); bool remove_from_combat_field_yes(CHAR_DATA *ch); void act_to_non_java(char *arg, CHAR_DATA *ch) { CHAR_DATA *c; if (!ch->in_room) return; for (c=ch->in_room->more->people;c;c=c->next_in_room) { if (IS_JAVA(c)) continue; if (c==ch) continue; act(arg,c,NULL,ch,TO_CHAR); } return; } #ifndef OLD_FIGHT bool nobody_near(CHAR_DATA *c) { int x,y; COMBAT_FIELD *cf; if (!c->fgt || !c->fgt->field) return TRUE; x=c->fgt->pos_x; y=c->fgt->pos_y; cf=c->fgt->field; if (x>0 && cf->map[x-1][y]!=NULL) return FALSE; if (x<6 && cf->map[x+1][y]!=NULL) return FALSE; if (y>0 && cf->map[x][y-1]!=NULL) return FALSE; if (y<6 && cf->map[x][y+1]!=NULL) return FALSE; return TRUE; } /* For field_move, we can be sure fgt exists, as well as field and other related sub-structures. POSSIBLE debug trap later if problems arise. */ void field_move(CHAR_DATA *ch, int dir) { int i,j; int x,y; int tx,ty; char buf[500]; COMBAT_FIELD *f=ch->fgt->field; if (dir==-1) return; if (ch->position==POSITION_GROUNDFIGHTING) return; i=ch->fgt->pos_x; j=ch->fgt->pos_y; if (dir==DIR_NORTH && j>0) { x=i; y=j-1; } else if (dir==DIR_SOUTH && j<6) { x=i; y=j+1; } else if (dir==DIR_EAST && i<6) { x=i+1; y=j; } else if (dir==DIR_WEST && i>0) { x=i-1; y=j; } else { /* moving off battle field... */ /*fprintf(stderr,"%s tried to move in dir %d.\n",NAME(ch),dir); */ send_to_char("If you want to flee, type FLEE...\n\r",ch); return; } if (f->map[x][y]!=NULL) { /* Okay, we moved INTO someone.. attack!! */ if (IS_PLAYER(ch) && IS_PLAYER(f->map[x][y]) && FIGHTING(f->map[x][y])!=ch && FIGHTING(ch)!=f->map[x][y] && !not_is_same_align(ch,f->map[x][y])) { return; } if (IS_MOB(ch) && IS_MOB(f->map[x][y]) && FIGHTING(ch)!=f->map[x][y] && FIGHTING(f->map[x][y])!=ch) { return; } /* CHECK FOR FRIENDS/ETC HERE */ hitop=FALSE; multi_hit(ch,f->map[x][y],TYPE_UNDEFINED); if (hitop) { java_hit_field(f,ch,i,j,x,y); } else { /* Send miss here? */ } } else { /*for (tx=0;tx<7;tx++) { for (ty=0;ty<7;ty++) { if (f->map[tx][ty]) {*/ java_update_field(f,ch,i,j,x,y); /*} } }*/ f->map[i][j]=NULL; f->map[x][y]=ch; ch->fgt->pos_x=x; ch->fgt->pos_y=y; if (ch->move<4) { send_to_char("You are too exhausted to move!\n\r",ch); return; } SUBMOVE(ch,3); /* sprintf(buf,"$N moves to %d, %d.",x,y); act_to_non_java(buf,ch);*/ /* if (!IS_JAVA(ch)) { sprintf(buf,"You advance.\n\r"); send_to_char(buf,ch); }*/ } return; } #endif /* Returns direction if the mob/target is next to the person on the field */ int is_fighting_near(CHAR_DATA *ch, CHAR_DATA *target) { #ifndef OLD_FIGHT COMBAT_FIELD *cf=ch->fgt->field; int i=ch->fgt->pos_x; int j=ch->fgt->pos_y; if (cf==NULL) return -1; if (!target) { remove_from_combat_field(ch); return -1; } check_fgt(target); if (cf!=target->fgt->field) return -1; if (i>0 && cf->map[i-1][j]==target) return DIR_WEST; if (i<6 && cf->map[i+1][j]==target) return DIR_EAST; if (j>0 && cf->map[i][j-1]==target) return DIR_NORTH; if (j<6 && cf->map[i][j+1]==target) return DIR_SOUTH; return -1; #else return 1; #endif } /* This updates all combat field movement, etc */ void combat_field_update(void) { #ifndef OLD_FIGHT COMBAT_FIELD *f; int pif=0; CHAR_DATA *cif=NULL; COMBAT_FIELD *f_next; int i,j; for (f=field_list;f!=NULL;f=f_next) { f_next=f->next; for (i=0;i<7;i++) { for (j=0; j<7; j++) { if (f->map[i][j]) { CHAR_DATA *c=f->map[i][j]; cif=c; pif++; if (!c->fgt) continue; /* ERROR */ if ((--c->fgt->field_ticks) == 0) { if (c->fgt->next_command==NULL && (IS_MOB(c) /*|| !IS_JAVA(c)*/ || c->fgt->auto_toggles || (is_fighting_near(c,FIGHTING(c))!=-1 && c->fgt->next_command==NULL))) { /* CHANGE AUTOS LATER */ if (is_fighting_near(c,FIGHTING(c))!=-1) { field_move(c,is_fighting_near(c,FIGHTING(c))); } else { field_move(c,find_attack_direction(c,FIGHTING(c))); } } else { if (c->fgt->next_command) { interpret(c,c->fgt->next_command); } } if (c->fgt) { c->fgt->field_ticks=number_range(FIELD_TICK_WAIT-1,FIELD_TICK_WAIT+1); if (nobody_near(c)) { c->fgt->field_ticks--; if (IS_MOB(c) && number_range(1,2)==2) c->fgt->field_ticks--; } /* Add speed-up enhancements here */ if (c->fgt->next_command) { java_cnc(c); free(c->fgt->next_command); } c->fgt->next_command=NULL; } } } } } if (pif==1 && cif!=NULL && FIGHTING(cif)==NULL) { remove_from_combat_field_yes(cif); } } #endif return; } /* Returns TRUE if ch will attack victim, FALSE if ch will just go for target and ignore victim */ #ifndef OLD_FIGHT bool good_hit(CHAR_DATA *ch, CHAR_DATA *victim) { if (IS_MOB(ch) && IS_PLAYER(victim)) return TRUE; if (not_is_same_align(ch,victim)) return TRUE; return FALSE; } /* Returns best direction for ch to attack victim */ /* 0,0 6,0 */ /* */ /* 0,6 6,6 */ int find_attack_direction(CHAR_DATA *ch, CHAR_DATA *victim) { COMBAT_FIELD *cf; int i,j,x,y; if (!victim) return -1; if (!ch->fgt || !victim->fgt) return -1; if ( (cf=ch->fgt->field) == NULL ) return -1; if (cf!=victim->fgt->field) return -1; i=ch->fgt->pos_x; j=ch->fgt->pos_y; x=victim->fgt->pos_x; y=victim->fgt->pos_y; if (i<x && j<y) { if (cf->map[i][j+1]!=NULL && cf->map[i][j+1]!=victim && !good_hit(ch,cf->map[i][j+1])) return DIR_NORTH; if (cf->map[i+1][j]!=NULL && cf->map[i+1][j]!=victim && !good_hit(ch,cf->map[i+1][j])) return DIR_WEST; return ((number_range(1,2)==2)?DIR_SOUTH:DIR_EAST); } if (i>x && j>y) { if (cf->map[i][j-1]!=NULL && cf->map[i][j-1]!=victim && !good_hit(ch,cf->map[i][j-1])) return DIR_EAST; if (cf->map[i-1][j]!=NULL && cf->map[i-1][j]!=victim && !good_hit(ch,cf->map[i-1][j])) return DIR_SOUTH; return ((number_range(1,2)==2)?DIR_NORTH:DIR_WEST); } if (i>x && j<y) { if (cf->map[i][j+1]!=NULL && cf->map[i][j+1]!=victim && !good_hit(ch,cf->map[i][j+1])) return DIR_NORTH; if (cf->map[i-1][j]!=NULL && cf->map[i-1][j]!=victim && !good_hit(ch,cf->map[i-1][j])) return DIR_EAST; return ((number_range(1,2)==2)?DIR_SOUTH:DIR_WEST); } if (i<x && j>y) { if (cf->map[i][j-1]!=NULL && cf->map[i][j-1]!=victim && !good_hit(ch,cf->map[i][j-1])) return DIR_SOUTH; if (cf->map[i+1][j]!=NULL && cf->map[i+1][j]!=victim && !good_hit(ch,cf->map[i+1][j])) return DIR_WEST; return ((number_range(1,2)==2)?DIR_NORTH:DIR_EAST); } if (i<x) { if (cf->map[i+1][j]!=NULL && cf->map[i+1][j]!=victim && !good_hit(ch,cf->map[i+1][j])) return ((number_range(1,2)==2)?DIR_NORTH:DIR_SOUTH); return DIR_EAST; } if (i>x) { if (cf->map[i-1][j]!=NULL && cf->map[i-1][j]!=victim && !good_hit(ch,cf->map[i-1][j])) return ((number_range(1,2)==2)?DIR_NORTH:DIR_SOUTH); return DIR_WEST; } if (j<y) { if (cf->map[i][j+1]!=NULL && cf->map[i][j+1]!=victim && !good_hit(ch,cf->map[i][j+1])) return ((number_range(1,2)==2)?DIR_EAST:DIR_WEST); return DIR_SOUTH; } if (j>y) { if (cf->map[i][j-1]!=NULL && cf->map[i][j-1]!=victim && !good_hit(ch,cf->map[i][j-1])) return ((number_range(1,2)==2)?DIR_EAST:DIR_WEST); return DIR_NORTH; } return -1; } int find_flee_direction(CHAR_DATA *ch, CHAR_DATA *victim) { COMBAT_FIELD *cf; int i,j,x,y; if (!ch->fgt || !victim->fgt) return -1; if ( (cf=ch->fgt->field) == NULL ) return -1; if (cf!=victim->fgt->field) return -1; i=ch->fgt->pos_x; j=ch->fgt->pos_y; x=victim->fgt->pos_x; y=victim->fgt->pos_y; if (i<x && j<y) return ((number_range(1,2)==2)?DIR_NORTH:DIR_WEST); if (i>x && j>y) return ((number_range(1,2)==2)?DIR_SOUTH:DIR_EAST); if (i>x && j<y) return ((number_range(1,2)==2)?DIR_NORTH:DIR_EAST); if (i<x && j>y) return ((number_range(1,2)==2)?DIR_SOUTH:DIR_WEST); if (i<x) return DIR_WEST; if (i>x) return DIR_EAST; if (j<y) return DIR_NORTH; if (j>y) return DIR_SOUTH; return -1; } COMBAT_FIELD *new_combat_field(void) { COMBAT_FIELD *cf; if (!free_field_list) { cf=mem_alloc(sizeof(*cf)); } else { cf=free_field_list; free_field_list=free_field_list->next; } bzero(cf,sizeof(*cf)); cf->next=field_list; field_list=cf; return cf; } void free_combat_field(COMBAT_FIELD *cf) { COMBAT_FIELD *cc; if (cf==field_list) { field_list=field_list->next; cf->next=free_field_list; free_field_list=cf; return; } for (cc=field_list;cc!=NULL;cc=cc->next) { if (cc->next==cf) { cc->next=cf->next; cf->next=free_field_list; free_field_list=cf; } } /* Uh oh, not found.. don't worry about it */ return; } #endif /* ------------------------------------------------------------------------ */ /* Create a combat field if neither the char or victim is in one already */ /* If one is, use that one, place appropriately. If both have a combat */ /* field, then something somewhere is messed up. */ /* Please note this only adds the character to the field */ /* ------------------------------------------------------------------------ */ void add_to_combat_field(CHAR_DATA *ch, CHAR_DATA *victim) { #ifndef OLD_FIGHT int i,j; COMBAT_FIELD *cf; check_fgt(ch); if (!victim) { fprintf(stderr,"NULL victim in add to combat field.\n"); return; } check_fgt(victim); if (ch->fgt->field) return; /* This IS possible.. perhas give them notification? */ if (ch->fgt->field && ch->fgt->field!=victim->fgt->field) { /* We're screwed... char in combat field, but not the same as victim, or the victim isn't in one. */ return; } ch->fgt->field_ticks=number_range(2,5); if (victim->fgt->field) { int xx,yy; xx=0; yy=0; cf=victim->fgt->field; xx=victim->fgt->pos_x; yy=victim->fgt->pos_y; /* Place ch in victim's combat field */ if (closeto && xx<6 && cf->map[xx+1][yy]==NULL) { cf->map[xx+1][yy]=ch; ch->fgt->pos_x=xx+1; ch->fgt->pos_y=yy; ch->fgt->field=cf; java_add_to_field(ch->fgt->field,ch,xx+1,yy); return; } if (closeto && xx>0 && cf->map[xx-1][yy]==NULL) { cf->map[xx-1][yy]=ch; ch->fgt->pos_x=xx-1; ch->fgt->pos_y=yy; ch->fgt->field=cf; java_add_to_field(ch->fgt->field,ch,xx-1,yy); return; } if (closeto && yy>0 && cf->map[xx][yy-1]==NULL) { cf->map[xx][yy-1]=ch; ch->fgt->pos_x=xx; ch->fgt->pos_y=yy-1; ch->fgt->field=cf; java_add_to_field(ch->fgt->field,ch,xx,yy-1); return; } if (closeto && yy<6 && cf->map[xx][yy+1]==NULL) { cf->map[xx][yy+1]=ch; ch->fgt->pos_x=xx; ch->fgt->pos_y=yy+1; ch->fgt->field=cf; java_add_to_field(ch->fgt->field,ch,xx,yy+1); return; } if (IS_MOB(ch)) { /* Mob, place at top */ for (i=0; i<7; i++) { for (j=0; j<7; j+=2) { if (cf->map[i][j]!=NULL) continue; cf->map[i][j]=ch; ch->fgt->pos_x=i; ch->fgt->pos_y=j; ch->fgt->field=cf; java_add_to_field(ch->fgt->field,ch,i,j); return; } for (j=1; j<7; j+=2) { if (cf->map[i][j]!=NULL) continue; cf->map[i][j]=ch; ch->fgt->pos_x=i; ch->fgt->pos_y=j; ch->fgt->field=cf; java_add_to_field(ch->fgt->field,ch,i,j); return; } } /* Holy shit.. no room in the WHOLE field - error here */ } else { for (i=6; i>=0; i--) { for (j=5; j>=0; j-=2) { if (cf->map[i][j]!=NULL) continue; cf->map[i][j]=ch; ch->fgt->pos_x=i; ch->fgt->pos_y=j; ch->fgt->field=cf; java_add_to_field(ch->fgt->field,ch,i,j); return; } for (j=6; j>=0; j-=2) { if (cf->map[i][j]!=NULL) continue; cf->map[i][j]=ch; ch->fgt->pos_x=i; ch->fgt->pos_y=j; ch->fgt->field=cf; java_add_to_field(ch->fgt->field,ch,i,j); return; } } /* Holy shit.. no free space for this player.. error */ } } /* Victim isn't in a combat field.. we have to make one. */ cf=new_combat_field(); if (IS_MOB(ch)) { i=2; j=0; } else { i=4; j=6; } ch->fgt->pos_x=i; ch->fgt->pos_y=j; ch->fgt->field=cf; cf->map[i][j]=ch; java_add_to_field(ch->fgt->field,ch,i,j); /* Don't place victim in the field yet... perhaps later? */ #endif return; } bool remove_from_combat_field_yes(CHAR_DATA *ch) { /* returns TRUE if nobody left on field */ #ifndef OLD_FIGHT int i,j; COMBAT_FIELD *cf; if (!ch->fgt) return FALSE; cf=ch->fgt->field; if (!cf) return FALSE; if (cf->map[ch->fgt->pos_x][ch->fgt->pos_y]!=ch) { /* Character not found at marked position! */ return FALSE; } cf->map[ch->fgt->pos_x][ch->fgt->pos_y]=NULL; java_remove_from_combat_field(cf,ch,ch->fgt->pos_x,ch->fgt->pos_y); ch->fgt->pos_x=0; ch->fgt->pos_y=0; ch->fgt->field=NULL; /* fprintf(stderr,"Removed %s from combat_field yes.\n",NAME(ch)); */ /* Now check if we can free the field */ for (i=0; i<7; i++) { for (j=0; j<7; j++) { if (cf->map[i][j]!=NULL) return FALSE; } } /* Nobody left, let's free this baby */ free_combat_field(cf); /*fprintf(stderr,"Free'd the combat field.\n"); */ #endif return TRUE; } bool remove_from_combat_field(CHAR_DATA *ch) { /* returns TRUE if nobody left on field */ #ifndef OLD_FIGHT int i,j; COMBAT_FIELD *cf; if (!ch->fgt) return FALSE; cf=ch->fgt->field; if (!cf) return FALSE; if (cf->map[ch->fgt->pos_x][ch->fgt->pos_y]!=ch) { /* Character not found at marked position! */ return FALSE; } /* Now check if there are any others left fighting this bloke */ for (i=0; i<7; i++) { for (j=0; j<7; j++) { if (!cf->map[i][j]) continue; if (cf->map[i][j]->in_room != ch->in_room) continue; if (cf->map[i][j]->position<=POSITION_STUNNED) continue; if (FIGHTING(cf->map[i][j])==ch) return FALSE; } } java_remove_from_combat_field(cf,ch,ch->fgt->pos_x,ch->fgt->pos_y); cf->map[ch->fgt->pos_x][ch->fgt->pos_y]=NULL; ch->fgt->pos_x=0; ch->fgt->pos_y=0; ch->fgt->field=NULL; /* fprintf(stderr,"Removed %s from combat field.\n",NAME(ch)); */ /* Now check if we can free the field */ for (i=0; i<7; i++) { for (j=0; j<7; j++) { if (cf->map[i][j]!=NULL) return FALSE; } } /* Nobody left, let's free this baby */ free_combat_field(cf); /*fprintf(stderr,"Free'd the combat field.\n"); */ #endif return TRUE; }