Crossfire Mailing List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Some new spells



Here is a patch for some new spells in crossfire. I have diffed against the base
crossfire0.87.8, so it also contains my last patch for bracing. I have also added
'.' as a command. '.' will fire at you, so you can apply a spell to yourself.
Note that it is just '.' not shift-. as shift-. is '>' which is already used.

The spells added are:
create fire wall - creates a temporary wall of fire. Use the 'strength' command
to make the spell last longer.
create frost wall - creates a temporary wall of frost.
holy word - similar to turn undead, but does a bit of damage as well.
invisibility - makes you invisible, but if you hit anything or cast a spell you
become visible again.
improved invisibility - same affect as an amulet.
minor, medium, major healing - heals you or someone next to you.
heal - heal to full.
create food - creates a food next to you.
earth to dust - destroys earth walls around you. The strength determines how far 
around you is affected. Strength of 3 affects one square away, strength of 6 
affects 2 squares, etc up to 15 strength. Also, you cannot affect a range of more
than your level.
armour - gives you temporary magic armour. Again strength affects the armour class
produced. ac = 8-(strength/3). You can't put more than 3 times your level in
strength points. You can also cast this on someone else.
strength - temporarily change strength. strength = 15+(strength/3). You can't put
more than 3 times your level in strength points. Note also that this strength
is absolute, magic items don't affect it. It may also reduce strength. It can also
be applied to someone else.
dexterity - as strength but affects dexterity.

I haven't tested these spells extensively, so please mail me any bug reports. 
Playtesting will probably also show whether the spellpoint cost or spell effect
needs any tweaking.

Enjoy,

   Rupert
------------------>8 cut here 8<------------------------------------------------
diff -c crossfire-0.87.8/define.h crossfire.local/define.h
*** crossfire-0.87.8/define.h	Thu Sep 24 16:24:16 1992
--- crossfire.local/define.h	Sat Oct  3 17:46:33 1992
***************
*** 177,183 ****
  
  #define NROFPFACES 10		/* How many player icons/classes there are */
  
! #define NROFREALSPELLS  22	/* NROFSPELLS will very soon be obsolete */
  
  #define NROFMATERIALS 8
  
--- 177,183 ----
  
  #define NROFPFACES 10		/* How many player icons/classes there are */
  
! #define NROFREALSPELLS  36	/* NROFSPELLS will very soon be obsolete */
  
  #define NROFMATERIALS 8
  
diff -c crossfire-0.87.8/global.h crossfire.local/global.h
*** crossfire-0.87.8/global.h	Thu Sep 24 16:24:16 1992
--- crossfire.local/global.h	Mon Oct  5 11:18:46 1992
***************
*** 167,172 ****
--- 167,174 ----
    unsigned char key_down;     /* Last move-key still held down */
    unsigned char mode;         /* Mode of player: */
    unsigned char berzerk;      /* Affects usage of CTRL-direction */
+   unsigned braced:1;		  /* Will not move if braced, only attack */
+   unsigned tmp_invis:1;		  /* Will invis go away when we attack ? */
    /* 0=normal, 1=pick up while walking, 2=stop after pick, 3=stop before pick */
    unsigned char state,infoline;
    unsigned char writing;   /* When true, the player is writing text */
***************
*** 194,200 ****
    unsigned short scrollsize_food;  /* How large the last scrollbar was */
    short shootstrength;     /* Strength of spell */
    object *golem;           /* Which golem is controlled */
!   living orig_stats;       /* Can be less in case of poisoning */
    living last_stats;       /* Last stats drawn with draw_stats() */
    float last_speed;
    signed long last_value;  /* Same usage as last_stats */
--- 196,204 ----
    unsigned short scrollsize_food;  /* How large the last scrollbar was */
    short shootstrength;     /* Strength of spell */
    object *golem;           /* Which golem is controlled */
!   living orig_stats;       /* hijacked for cast_change_attr by rgg */
!   short stat_count[6];	   /* counter for spell-modified stats */
!   short ac_count;          /* counter for aormour spell */
    living last_stats;       /* Last stats drawn with draw_stats() */
    float last_speed;
    signed long last_value;  /* Same usage as last_stats */
diff -c crossfire-0.87.8/input.c crossfire.local/input.c
*** crossfire-0.87.8/input.c	Thu Sep 24 16:24:17 1992
--- crossfire.local/input.c	Mon Oct  5 11:50:17 1992
***************
*** 1218,1232 ****
      draw_stats(pl->ob);
      return 0;
    }
!   if(!strncmp(str,"speed",buf_len)) {
!     int i;
!     if(p==NULL||!sscanf(++p,"%d", &i)) {
!       sprintf(errmsg,"Current speed is %d",max_time);
!       draw_info(op,errmsg);
        return 0;
      }
!     max_time=i;
!     draw_info(op,"The speed is changed.");
      return 0;
    }
    if(!strncmp(str,"goto",buf_len)) {
--- 1218,1261 ----
      draw_stats(pl->ob);
      return 0;
    }
!   if((!strncmp(str,"sp",buf_len))){
!     if(!strncmp(str,"speed",(buf_len<3?3:buf_len))) {
!       int i;
!       if(p==NULL||!sscanf(++p,"%d", &i)) {
!         sprintf(errmsg,"Current speed is %d",max_time);
!         draw_info(op,errmsg);
!         return 0;
!       }
!       max_time=i;
!       draw_info(op,"The speed is changed.");
        return 0;
      }
!     iii = 0;
!     thing[0] = '\0';
!     if(p==NULL||!sscanf(++p,"%s %d",thing,&iii)) {
!        draw_info(op,"Who?");
!        return 0;
!     }
!     if (thing==NULL){
!        draw_info(op,"Who?");
!        return 0;
!     }
!     for(pl=first_player;pl!=NULL;pl=pl->next) 
!        if(!strcmp(pl->ob->name,thing))   
!          if (iii!=0){ 
!             sprintf(buf,"%s has been altered.",pl->ob->name);
!             draw_info(op,buf);
!             pl->ob->stats.sp = iii;    
!          } 
!          else{
!             sprintf(buf,"%s has been charged.",pl->ob->name);
!             draw_info(op,buf);
!             pl->ob->stats.sp = pl->ob->stats.maxsp;
!          } 
!     if(pl==NULL){
!        sprintf(buf,"Who?");
!        draw_info(op,buf);
!     }
      return 0;
    }
    if(!strncmp(str,"goto",buf_len)) {
***************
*** 1362,1396 ****
      return 0;
    }
  
-   if((!strncmp(str,"sp",buf_len))){
-     iii = 0;
-     thing[0] = '\0';
-     if(p==NULL||!sscanf(++p,"%s %d",thing,&iii)) {
-        draw_info(op,"Who?");
-        return 0;
-     }
-     if (thing==NULL){
-        draw_info(op,"Who?");
-        return 0;
-     }
-     for(pl=first_player;pl!=NULL;pl=pl->next) 
-        if(!strcmp(pl->ob->name,thing))   
-          if (iii!=0){ 
-             sprintf(buf,"%s has been altered.",pl->ob->name);
-             draw_info(op,buf);
-             pl->ob->stats.sp = iii;    
-          } 
-          else{
-             sprintf(buf,"%s has been charged.",pl->ob->name);
-             draw_info(op,buf);
-             pl->ob->stats.sp = pl->ob->stats.maxsp;
-          } 
-     if(pl==NULL){
-        sprintf(buf,"Who?");
-        draw_info(op,buf);
-     }
-     return 0;
-   }
    if((!strncmp(str,"food",buf_len))){
      iii = 0;
      thing[0] = '\0';
--- 1391,1396 ----
***************
*** 1544,1549 ****
--- 1544,1553 ----
      return parse_writing(op,k);
    else {
      switch(k) {
+     case '.': pl->fire_on=1;
+               move_player(op,0,op->direction);
+ 	      pl->fire_on=0;
+ 	      break;
      case 'l': move_player(op,3,1);break;
      case 'h': move_player(op,7,0);break;
      case 'j': move_player(op,5,3);break;
***************
*** 1713,1718 ****
--- 1717,1732 ----
        break;
      case 's': if (IS_WIZ(op))
        (void) fprintf(stderr,"%d used, %d free.\n",count_used(),count_free());
+ 	  		  else {
+ 			  	if (op->contr->braced) {
+ 					op->contr->braced = 0;
+ 					draw_info(op, "You are no longer braced.");
+ 				}
+ 				else {
+ 					op->contr->braced = 1;
+ 					draw_info(op, "You are now braced.");
+ 				}
+ 			  }
        break;
      case 'S': if(IS_WIZ(op))
        (void) ss_dump_table(1);
diff -c crossfire-0.87.8/living.c crossfire.local/living.c
*** crossfire-0.87.8/living.c	Thu Sep 24 16:24:17 1992
--- crossfire.local/living.c	Mon Oct  5 11:14:41 1992
***************
*** 27,65 ****
  
  #include "living.h"
  
  int change_abil(object *op, object *tmp) {
!   int flag=IS_APPLIED(tmp)?1:-1,i;
    if(tmp->type==POTION) {
!     if((tmp->stats.Str&&((i=(op->stats.Str+flag*tmp->stats.Str))>
!          20+classbonus[op->contr->face][STR]||i<1))||
!        (tmp->stats.Dex&&((i=(op->stats.Dex+flag*tmp->stats.Dex))>
!          20+classbonus[op->contr->face][DEX]||i<1))||
!        (tmp->stats.Con&&((i=(op->stats.Con+flag*tmp->stats.Con))>
!          20+classbonus[op->contr->face][CON]||i<1))||
!        (tmp->stats.Wis&&((i=(op->stats.Wis+flag*tmp->stats.Wis))>
!          20+classbonus[op->contr->face][WIS]||i<1))||
!        (tmp->stats.Cha&&((i=(op->stats.Cha+flag*tmp->stats.Cha))>
!          20+classbonus[op->contr->face][CHA]||i<1))||
!        (tmp->stats.Int&&((i=(op->stats.Int+flag*tmp->stats.Int))>
!          20+classbonus[op->contr->face][INT]||i<1)))
!       return 0;
!   } else
!     if((tmp->stats.Int&&((i=(op->stats.Int+flag*tmp->stats.Int))>25||i<1))||
!        (tmp->stats.Dex&&((i=(op->stats.Dex+flag*tmp->stats.Dex))>25||i<1))||
!        (tmp->stats.Str&&((i=(op->stats.Str+flag*tmp->stats.Str))>25||i<1))||
!        (tmp->stats.Con&&((i=(op->stats.Con+flag*tmp->stats.Con))>25||i<1))||
!        (tmp->stats.Wis&&((i=(op->stats.Wis+flag*tmp->stats.Wis))>25||i<1))||
!        (tmp->stats.Cha&&((i=(op->stats.Cha+flag*tmp->stats.Cha))>25||i<1))||
!        (flag==1&&(op->immune&tmp->immune||
                    op->protected&tmp->protected||
!                   op->attacktype&tmp->attacktype)))
        return 0;
!   op->stats.Int+=flag*tmp->stats.Int,
!   op->stats.Dex+=flag*tmp->stats.Dex,
!   op->stats.Str+=flag*tmp->stats.Str,
!   op->stats.Wis+=flag*tmp->stats.Wis,
!   op->stats.Cha+=flag*tmp->stats.Cha,
!   op->stats.Con+=flag*tmp->stats.Con;
    if(flag==1)
      op->immune|=tmp->immune,
      op->protected|=tmp->protected,
--- 27,62 ----
  
  #include "living.h"
  
+ #define real_value(op,stat) (op->contr->stat_count[stat] ? \
+ 	get_attr_value(&(op->contr->orig_stats),stat) : \
+ 	get_attr_value(&(op->stats),stat) )
+ 
+ 
  int change_abil(object *op, object *tmp) {
!   int flag=IS_APPLIED(tmp)?1:-1,i,j;
    if(tmp->type==POTION) {
!     for(j=0;j<6;j++)
!       if(get_attr_value(&(tmp->stats),j) && ((real_value(op,j)+
!          flag*get_attr_value(&(tmp->stats),j)) > classbonus[op->contr->face][j]))
! 	   return 0;
!   } else {
!     for(j=0;j<6;j++)
!       if(get_attr_value(&(tmp->stats),j) && ((real_value(op,j)+
!          flag*get_attr_value(&(tmp->stats),j)) > 25))
! 	   return 0;
!      if(flag==1&&(op->immune&tmp->immune||
                    op->protected&tmp->protected||
!                   op->attacktype&tmp->attacktype))
        return 0;
!     }
!   for(j=0;j<6;j++)
!     if(op->contr->stat_count[j]) 
!       set_attr_value(&(op->contr->orig_stats),j,
!         get_attr_value(&(op->contr->orig_stats),j)+get_attr_value(&(tmp->stats),j));
!     else
!       set_attr_value(&(op->stats),j,
!         get_attr_value(&(op->stats),j)+get_attr_value(&(tmp->stats),j));
!       
    if(flag==1)
      op->immune|=tmp->immune,
      op->protected|=tmp->protected,
***************
*** 323,328 ****
--- 320,328 ----
            max=ARMOUR_SPEED(tmp)/10.0;
          break;
    }
+   /* apply armour spell effects */
+   if((op->stats.ac>op->contr->orig_stats.ac)&&(op->contr->ac_count))
+     op->stats.ac=op->contr->orig_stats.ac;
    if(op->stats.dam<1)
      op->stats.dam=1;
    op->speed=1.0+speed_bonus[op->stats.Dex];
diff -c crossfire-0.87.8/main.c crossfire.local/main.c
*** crossfire-0.87.8/main.c	Thu Sep 24 16:24:17 1992
--- crossfire.local/main.c	Mon Oct  5 11:19:52 1992
***************
*** 47,53 ****
    draw_info(op,"\"  = speak        ' = command     Q = quit");
    draw_info(op,"i  = inventory    , = get         : = look");
    draw_info(op,"<> = rotate       d = drop        ? = help");
!   draw_info(op,"a  = apply        A = apply below t = throw");
    draw_info(op,"e  = examine      E = examine below");
    draw_info(op,"+- = change spell @ = autopick");
    draw_info(op,"C  = reconfigure movement (cursor) keys");
--- 47,53 ----
    draw_info(op,"\"  = speak        ' = command     Q = quit");
    draw_info(op,"i  = inventory    , = get         : = look");
    draw_info(op,"<> = rotate       d = drop        ? = help");
!   draw_info(op,"a  = apply        A = apply below s = brace");
    draw_info(op,"e  = examine      E = examine below");
    draw_info(op,"+- = change spell @ = autopick");
    draw_info(op,"C  = reconfigure movement (cursor) keys");
***************
*** 765,770 ****
--- 765,775 ----
  void fire(object *op,int dir) {
    object *tmp,*weap;
  
+   if (op->contr->tmp_invis) {		/* tmp invis goes away now */
+     op->invisible = 0;
+     op->contr->tmp_invis = 0;
+     update_object(op);
+   }
    switch(op->contr->shoottype) {
    case 0:
      return;
***************
*** 1179,1185 ****
    if(op->contr->fire_on)
      fire(op,dir);
    else
!     if(!move_ob(op,dir)&&!out_of_map(op->map,op->x+dx,op->y+dy)) {
        stack=tmp=get_map_ob(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir]);
        while(stack) {
  	if (IS_ALIVE(stack) || CAN_ROLL(stack)) tmp = stack;
--- 1184,1190 ----
    if(op->contr->fire_on)
      fire(op,dir);
    else
!     if((op->contr->braced||!move_ob(op,dir))&&!out_of_map(op->map,op->x+dx,op->y+dy)) {
        stack=tmp=get_map_ob(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir]);
        while(stack) {
  	if (IS_ALIVE(stack) || CAN_ROLL(stack)) tmp = stack;
***************
*** 1195,1205 ****
              hit_player(tmp,9999,op,AT_PHYSICAL); /* Break through the door */
            }
          }
!         if(tmp->type==PLAYER&&op->contr->peaceful)
            (void) push_ob(tmp,dir,op);
!         else if(CAN_ROLL(tmp))
            recursive_roll(tmp,dir,op);
          else if(tmp->stats.hp>=0&&IS_ALIVE(tmp)) {
            attack_ob(tmp,op);
            op->speed_left-=op->contr->weapon_sp-1;
  #if 0
--- 1200,1215 ----
              hit_player(tmp,9999,op,AT_PHYSICAL); /* Break through the door */
            }
          }
!         if(tmp->type==PLAYER&&op->contr->peaceful&&(!op->contr->braced))
            (void) push_ob(tmp,dir,op);
!         else if(CAN_ROLL(tmp)&&(!op->contr->braced))
            recursive_roll(tmp,dir,op);
          else if(tmp->stats.hp>=0&&IS_ALIVE(tmp)) {
+ 	  if (op->contr->tmp_invis) {		/* tmp invis goes away now */
+ 	    op->invisible = 0;
+ 	    op->contr->tmp_invis = 0;
+ 	    update_object(op);
+ 	  }
            attack_ob(tmp,op);
            op->speed_left-=op->contr->weapon_sp-1;
  #if 0
***************
*** 1223,1232 ****
--- 1233,1261 ----
  void do_some_living(object *op) {
    char buf[MAX_BUF];
    object *tmp;
+   int	j;
    int last_food=op->stats.food;
    int gen_hp=(op->contr->gen_hp+1)*op->stats.maxhp;
    int gen_sp=(op->contr->gen_sp+1)*op->stats.maxsp;
  
+   /* reduce spell increased attributes */
+   for(j=0;j<6;j++) {
+     if(op->contr->stat_count[j]) {
+       op->contr->stat_count[j]--;
+       if(!op->contr->stat_count[j]) {
+          set_attr_value(&(op->stats),j,get_attr_value(&(op->contr->orig_stats),j));
+ 	 fix_player(op);
+       }
+     }	 
+   }
+   /* reduce armour spell */
+   if(op->contr->ac_count) {
+     op->contr->ac_count--;
+     if(!op->contr->ac_count) {
+       op->contr->ac_count=20;
+       fix_player(op);
+     }
+   }
    if(!op->state&&op->contr->golem==NULL&&--op->last_sp<0) {
      if(op->stats.sp<op->stats.maxsp)
        op->stats.sp++,op->stats.food--;
diff -c crossfire-0.87.8/player.c crossfire.local/player.c
*** crossfire-0.87.8/player.c	Thu Sep 24 16:24:17 1992
--- crossfire.local/player.c	Mon Oct  5 11:19:48 1992
***************
*** 225,230 ****
--- 225,235 ----
    p->last_stats.wc=0,   p->last_stats.ac=0;
    p->last_stats.sp=0,   p->last_stats.maxsp=0;
    p->last_stats.exp= -1,p->last_stats.food=0;
+   bzero(&(p->orig_stats),sizeof(living));
+   for(i=0;i<6;i++)
+     p->stat_count[i]=0;
+   p->orig_stats.ac=20;
+   p->ac_count=0;
    p->digestion=0,p->gen_hp=0,p->gen_sp=0;
    p->chosen_spell=0;
    p->last_spell= -1;
diff -c crossfire-0.87.8/proto.h crossfire.local/proto.h
*** crossfire-0.87.8/proto.h	Thu Sep 24 16:24:16 1992
--- crossfire.local/proto.h	Mon Oct  5 10:43:21 1992
***************
*** 256,262 ****
  extern int check_spell_known ( object *op, int sp );
  extern void cast_spell ( object *op, int dir, int type );
  extern int earth_wall ( object *op, int dir );
! extern int dimmension_door ( object *op, int dir );
  extern int summon_monster ( object *op, int dir, char *name );
  extern int create_bomb ( object *op, int dir, char *name );
  extern int ok_to_put_more ( mapstruct *m, int x, int y, object *op, int immune_stop );
--- 256,262 ----
  extern int check_spell_known ( object *op, int sp );
  extern void cast_spell ( object *op, int dir, int type );
  extern int earth_wall ( object *op, int dir );
! extern int dimension_door ( object *op, int dir );
  extern int summon_monster ( object *op, int dir, char *name );
  extern int create_bomb ( object *op, int dir, char *name );
  extern int ok_to_put_more ( mapstruct *m, int x, int y, object *op, int immune_stop );
***************
*** 276,281 ****
--- 276,288 ----
  extern int explode_object ( object *op );
  extern void move_fired_arch ( object *op );
  extern void move_bullet ( object *op );
+ extern int cast_invis( object *op, int spell_type );
+ extern int cast_heal( object *op,int dir,int spell_type );
+ extern int cast_change_attr( object *op,int dir,int spell_type );
+ extern void set_attr_value( living *stats, int attr, signed char value );
+ extern signed char get_attr_value( living *stats, int attr );
+ extern int cast_create_obj( object *op,int dir,char *archetype ); 
+ extern int cast_earth2dust( object *op );
  extern int isqrt ( int n );
  extern void set_magic ( mapstruct *m, object *op, int magic );
  extern char *describe_ring ( object *op );
diff -c crossfire-0.87.8/spells.c crossfire.local/spells.c
*** crossfire-0.87.8/spells.c	Thu Sep 24 16:24:17 1992
--- crossfire.local/spells.c	Mon Oct  5 12:38:20 1992
***************
*** 29,34 ****
--- 29,41 ----
  #include "global.h"
  #include "spells.h"
  
+ #define STR 0
+ #define DEX 1
+ #define CON 2
+ #define WIS 3
+ #define CHA 4
+ #define INT 5
+ 
  spell *find_spell(int spelltype) {
    if(spelltype<0||spelltype>NROFREALSPELLS)
      return NULL;
***************
*** 99,108 ****
      success=summon_monster(op,dir,"air_elemental");
      break;
    case SP_D_DOOR:
!     success=dimmension_door(op,dir);
      break;
!   case SP_WALL:
!     success=earth_wall(op,dir);
      break;
    case SP_PARALYZE:
      success=cast_cone(op,dir,0,5,SP_PARALYZE);
--- 106,121 ----
      success=summon_monster(op,dir,"air_elemental");
      break;
    case SP_D_DOOR:
!     success=dimension_door(op,dir);
      break;
!   case SP_FIRE_WALL:
!   case SP_FROST_WALL:
!     if (op->stats.sp < s->sp+op->contr->shootstrength) {
!       draw_info(op,"Not enough spellpoints for that strength.");
!       return;
!     }
!   case SP_EARTH_WALL:
!     success=magic_wall(op,dir,type);
      break;
    case SP_PARALYZE:
      success=cast_cone(op,dir,0,5,SP_PARALYZE);
***************
*** 123,149 ****
    case SP_POISON_CLOUD:
      success=fire_arch(op,dir,"spellball");
      break;
    }
    if(success)
      op->stats.sp-=s->sp;
  }
  
! int earth_wall(object *op,int dir) {
    object *tmp;
    if(blocked(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir])) {
      draw_info(op,"Something is in the way.");
      return 0;
    }
!   tmp=get_archetype("earthwall");
    tmp->x=op->x+freearr_x[dir],tmp->y=op->y+freearr_y[dir];
    insert_ob_in_map(tmp,op->map);
-   op->stats.sp-=6;
    draw_stats(op);
    draw(op);
    return 1;
  }
  
! int dimmension_door(object *op,int dir) {
    int dist;
    if(op->contr->count) {
      dist=op->contr->count;
--- 136,211 ----
    case SP_POISON_CLOUD:
      success=fire_arch(op,dir,"spellball");
      break;
+   case SP_HOLY_WORD:
+     success=cast_cone(op,dir,0,2+turn_bonus[op->stats.Wis],SP_HOLY_WORD);
+     break;
+   case SP_INVIS:
+     success=cast_invis(op, SP_INVIS);
+     break;
+   case SP_IMPROVED_INVIS:
+     success=cast_invis(op, SP_IMPROVED_INVIS);
+     break;
+   case SP_MINOR_HEAL:
+   case SP_MED_HEAL:
+   case SP_MAJOR_HEAL:
+   case SP_HEAL:
+     success=cast_heal(op,dir,type);
+     break;
+   case SP_CREATE_FOOD:
+     success=cast_create_obj(op,dir,"food");
+     break;
+   case SP_EARTH_DUST:
+     success=cast_earth2dust(op);
+     break;
+   case SP_STRENGTH:
+   case SP_DEXTERITY:
+     success=cast_change_attr(op,dir,type);
+     break;
    }
    if(success)
      op->stats.sp-=s->sp;
  }
  
! int magic_wall(object *op,int dir, int spell_type) {
    object *tmp;
    if(blocked(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir])) {
      draw_info(op,"Something is in the way.");
      return 0;
    }
!   switch(spell_type) {
!   case SP_EARTH_WALL:
!     tmp=get_archetype("earthwall");
!     break;
!   case SP_FIRE_WALL:
!     tmp=get_archetype("firebreath");
!     tmp->attacktype |= AT_MAGIC;
!     tmp->stats.hp=60 + op->contr->shootstrength*4;
!     tmp->stats.wc= -10 - op->level*2;
!     tmp->stats.food=1;			/* so it doesn't propagate */
!     op->stats.sp -= op->contr->shootstrength;
!     set_owner(tmp,op);
!     break;
!   case SP_FROST_WALL:
!     tmp=get_archetype("icestorm");
!     tmp->attacktype |= AT_MAGIC;
!     tmp->stats.hp=50 + op->contr->shootstrength*4;
!     tmp->stats.wc= -10 - op->level*2;
!     tmp->stats.food=1;			/* so it doesn't propagate */
!     op->stats.sp -= op->contr->shootstrength;
!     set_owner(tmp,op);
!     break;
!   default:
!     fprintf(stderr,"Unimplemented magic_wall spell: %d\n",spell_type);
!     return 0;
!   }
    tmp->x=op->x+freearr_x[dir],tmp->y=op->y+freearr_y[dir];
    insert_ob_in_map(tmp,op->map);
    draw_stats(op);
    draw(op);
    return 1;
  }
  
! int dimension_door(object *op,int dir) {
    int dist;
    if(op->contr->count) {
      dist=op->contr->count;
***************
*** 315,320 ****
--- 377,385 ----
      case SP_FEAR:
        tmp=get_archetype("fear");
        break;
+     case SP_HOLY_WORD:
+       tmp=get_archetype("holy_word");
+       break;
      default:
        fprintf(stderr,"Unimplemented spell: %d\n",spell_type);
        return 0;
***************
*** 620,623 ****
--- 685,867 ----
      return;
    }
    insert_ob_in_map(op,op->map);
+ }
+ 
+ int
+ cast_invis(object *op, int spell_type) {
+   switch(spell_type) {
+   case SP_INVIS: 
+     op->invisible+=300;
+     op->contr->tmp_invis = 1;
+     draw_info(op,"You can't see your hands!");
+     update_object(op);
+     break;
+   case SP_IMPROVED_INVIS:
+     if (op->invisible < 1000)
+     	op->invisible+=200;
+     else if (op->invisible < 2000)
+     	op->invisible+=100;
+     break;
+     }
+   return 1;
+ }
+ 
+ int
+ cast_heal(object *op,int dir,int spell_type) {
+   object *tmp;
+   int heal;
+ 
+   for(tmp=get_map_ob(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir]);tmp!=NULL; tmp=tmp->above)
+     if(tmp->type==PLAYER)
+       break;
+   if(tmp==NULL)		/* didn't find a player there */
+     return 0;
+ 
+   switch(spell_type) {
+   case SP_MINOR_HEAL:
+     heal=(RANDOM()%8)+1;
+     break;
+   case SP_MED_HEAL:
+     heal=(RANDOM()%6)+(RANDOM()%6)+(RANDOM()%6)+6;
+     break;
+   case SP_MAJOR_HEAL:
+     heal=(RANDOM()%8)+(RANDOM()%8)+(RANDOM()%8)+6;
+     break;
+   case SP_HEAL:
+     heal=1000;
+     break;
+   }
+   tmp->stats.hp+=heal;
+   if(tmp->stats.hp>tmp->stats.maxhp)
+     tmp->stats.hp=tmp->stats.maxhp;
+ 
+   return 1;
+ }
+ 
+ 
+ int
+ cast_change_attr(object *op,int dir,int spell_type) {
+   int	strength, attr;
+   object *tmp;
+ 
+   strength=(op->level*3<op->contr->shootstrength)?op->level*3:op->contr->shootstrength;
+   if(spell_type!=SP_ARMOUR)
+     strength=(strength>30)?30:strength;
+   if (op->stats.sp < strength) {
+     draw_info(op,"Not enough spellpoints for that strength.");
+     return 0;
+   }
+   strength/=3;
+   for(tmp=get_map_ob(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir]);tmp!=NULL; tmp=tmp->above)
+     if(tmp->type==PLAYER)
+       break;
+   if(tmp==NULL)		/* didn't find a player there */
+     return 0;
+ 
+   switch(spell_type) {
+   case SP_STRENGTH:
+     attr=STR;
+     break;
+   case SP_DEXTERITY:
+     attr=DEX;
+     break;
+   case SP_ARMOUR:
+     if(tmp->contr->orig_stats.ac<8-strength) {
+       draw_info(op,"A stronger armour spell already in use.");
+       return 0;
+     }
+     tmp->contr->orig_stats.ac=8-strength;
+     tmp->contr->ac_count=400;
+     op->stats.sp -= op->contr->shootstrength; 
+     fix_player(op);
+     return 1;
+   }
+   if(tmp->contr->stat_count[attr]==0)
+     set_attr_value(&(tmp->contr->orig_stats),attr,get_attr_value(&(tmp->stats),attr));
+   set_attr_value(&(tmp->stats),attr,15+strength);
+   tmp->contr->stat_count[attr]=300;
+ 
+   op->stats.sp -= op->contr->shootstrength; 
+   fix_player(op);
+   return 1;
+ }
+ 
+ void
+ set_attr_value(living *stats,int attr,signed char value) {
+   switch(attr) {
+   case STR:
+     stats->Str=value;
+     break;
+   case DEX:
+     stats->Dex=value;
+     break;
+   case CON:
+     stats->Con=value;
+     break;
+   case WIS:
+     stats->Wis=value;
+     break;
+   case CHA:
+     stats->Cha=value;
+     break;
+   case INT:
+     stats->Int=value;
+     break;
+   }
+ }
+ 
+ signed char
+ get_attr_value(living *stats,int attr) {
+   switch(attr) {
+   case STR:
+     return(stats->Str);
+   case DEX:
+     return(stats->Dex);
+   case CON:
+     return(stats->Con);
+   case WIS:
+     return(stats->Wis);
+   case CHA:
+     return(stats->Cha);
+   case INT:
+     return(stats->Int);
+   }
+ }
+ 
+ 
+ int
+ cast_create_obj(object *op,int dir,char *archetype) {
+   object *tmp;
+ 
+   if(blocked(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir])) {
+     draw_info(op,"Something is in the way.");
+     return 0;
+   }
+   tmp=get_archetype(archetype);
+   tmp->x=op->x+freearr_x[dir],tmp->y=op->y+freearr_y[dir];
+   insert_ob_in_map(tmp,op->map);
+   return 1;
+ }
+ 
+ 
+ int 
+ cast_earth2dust( object *op ) {
+   object *tmp;
+   int strength,i,j;
+ 
+   strength=(op->level*3<op->contr->shootstrength)?op->level*3:op->contr->shootstrength;
+   strength=(strength>15)?15:strength;
+   if (op->stats.sp < strength) {
+     draw_info(op,"Not enough spellpoints for that strength.");
+     return 0;
+   }
+   strength/=3;
+   for(i=-strength;i<strength;i++)
+     for(j=-strength;j<strength;j++) {
+       tmp=get_map_ob(op->map,op->x+i,op->y+j);
+       if(tmp&&tmp->type==EARTHWALL)
+         hit_player(tmp,9999,op,AT_MAGIC);
+     }
+   op->stats.sp -= op->contr->shootstrength; 
+   return 1;
  }
diff -c crossfire-0.87.8/spells.h crossfire.local/spells.h
*** crossfire-0.87.8/spells.h	Thu Sep 24 16:24:16 1992
--- crossfire.local/spells.h	Mon Oct  5 11:12:07 1992
***************
*** 36,43 ****
    SP_BULLET,SP_S_FIREBALL,SP_M_FIREBALL,SP_L_FIREBALL,SP_BURNING_HANDS,
    SP_S_LIGHTNING,SP_L_LIGHTNING,SP_M_MISSILE,SP_BOMB,
    SP_GOLEM,SP_FIRE_ELEM,SP_EARTH_ELEM,SP_WATER_ELEM,SP_AIR_ELEM,
!   SP_D_DOOR,SP_WALL,SP_PARALYZE,SP_ICESTORM,SP_MAGIC_MAPPING,
!   SP_TURN_UNDEAD,SP_FEAR,SP_POISON_CLOUD};
  
  spell spells[NROFREALSPELLS]={
  "magic bullet",        		1, 1,
--- 36,46 ----
    SP_BULLET,SP_S_FIREBALL,SP_M_FIREBALL,SP_L_FIREBALL,SP_BURNING_HANDS,
    SP_S_LIGHTNING,SP_L_LIGHTNING,SP_M_MISSILE,SP_BOMB,
    SP_GOLEM,SP_FIRE_ELEM,SP_EARTH_ELEM,SP_WATER_ELEM,SP_AIR_ELEM,
!   SP_D_DOOR,SP_EARTH_WALL,SP_FIRE_WALL,SP_FROST_WALL,SP_PARALYZE,
!   SP_ICESTORM,SP_MAGIC_MAPPING,SP_TURN_UNDEAD,SP_FEAR,SP_POISON_CLOUD, 
!   SP_HOLY_WORD,SP_INVIS,SP_IMPROVED_INVIS,SP_MINOR_HEAL,SP_MED_HEAL,
!   SP_MAJOR_HEAL,SP_HEAL,SP_CREATE_FOOD,SP_EARTH_DUST,SP_ARMOUR,
!   SP_STRENGTH,SP_DEXTERITY,};
  
  spell spells[NROFREALSPELLS]={
  "magic bullet",        		1, 1,
***************
*** 54,65 ****
  "summon earth elemental",	4,15,
  "summon water elemental",	5,15,
  "summon air elemental",		6,20,
! "dimmension door",      	9,10,
  "create earth wall",    	4, 6,
  "paralyze",			2, 5,
  "icestorm",			4,10,
  "magic mapping",		5,15,
  "turn undead",			1, 2,
  "fear",				4,10,
! "poison cloud",			2, 5
  };
--- 57,82 ----
  "summon earth elemental",	4,15,
  "summon water elemental",	5,15,
  "summon air elemental",		6,20,
! "dimension door",      		9,10,
  "create earth wall",    	4, 6,
+ "create fire wall",    		6, 9,
+ "create frost wall",    	7,12,
  "paralyze",			2, 5,
  "icestorm",			4,10,
  "magic mapping",		5,15,
  "turn undead",			1, 2,
  "fear",				4,10,
! "poison cloud",			2, 5,
! "holy word",                    4,10,
! "invisibility",                 3, 5,
! "improved invisibility",        6,15,
! "minor healing", 		1, 2,
! "medium healing",		3, 5,
! "major healing", 		5, 8,
! "heal",				8,15,
! "create food", 			2, 3,
! "earth to dust", 		1, 0, /* 3*strength */
! "armour",			1, 0, /* 3*strength */
! "strength",			1, 0, /* 3*strength */
! "dexterity", 			1, 0  /* 3*strength */
  };
-- 
Rupert G. Goldie, Research Scientist                rgg@aaii.oz.au
Australian Artificial Intelligence Institute        
Life's a bitch and then you die.