SoldierSide Magic System, brought to you bye: Dazzle :P

This *WILL* require you to know your code, there are afew
parts that i cannot help you with because my mud code is different
then yours.

This system is based on FF1mud's casting system, its a small
system, but well worth the time/effort to play-with!

What this system does, is allow you, as the player, to make the mud
more lively, by ensuring that when you cast, it takes time to cast, apposed
to making you wait after you've cast (joy)  Ontop of that, it stops casters
from doing things like, parry, dodge, and use their shield to block ;)

They don't attack while casting their spell, making them rather vulnerable
to attack, this is where good team-work and group-efforts are a must for a mud.

Especialy when your spell-caster is casting.  I do hope you enjoy it, i don't take
full credit for it, the creator of FF1 mud, deserves a large portion of it, i just
revamped it greatly for my mud, and decided to release it.. Enjoy..

If you wanna contact me.. msn me ldevil@hotmail.com

Anyways, here we go.


Here we go :)

in fight.c, in multi_hit, add this after the if(ch->position < POS_RESTING) check

if(ch->casting_spell)
	return;


in mob_hit, right before the OFF_AREA_ATTACK check, add this
if(ch->casting_spell)
	return;

in one_hit, before it figures out who the victim is (right after
the function defines)

    // Should NEVER happen!
    if(ch->casting_spell)
    	return;


in bool damage, in the check for parry and dodge statement,

it looked like this.

	    if ( dt >= TYPE_HIT && ch != victim)
	    {
	        if ( check_parry( ch, victim ) )
		    return FALSE;
		if ( check_dodge( ch, victim ) )
		    return FALSE;
		if ( check_shield_block(ch,victim))
		    return FALSE;
	    }

Make it look like this..

    if(!victim->casting_spell)	// Ensure the victim isn't casting.
    {
	    if ( dt >= TYPE_HIT && ch != victim)
	    {
	        if ( check_parry( ch, victim ) )
		    return FALSE;
		if ( check_dodge( ch, victim ) )
		    return FALSE;
		if ( check_shield_block(ch,victim))
		    return FALSE;
	    }
    }



in raw_kill, before the save_char_obj(victim); statement, add
free_cast(victim); // Make them stop casting ;)

in interp.c  in intepret,  find


if (!found)
{

right before the '!check_social' check, add the following.

	if(is_exact_name(command, "stop"))
	{
		if(ch->casting_spell)
		{
			free_cast(ch);
			send_to_char("You stop casting your spell.\n\r",ch);
			return;
		}
		else
		{
			free_cast(ch); // Just incase there was a problem!
			send_to_char("But your not casting anything!\n\r",ch);
			return;
		}
	}


right before the following statement

/*
 * Dispatch the command
 */

add the following

    if(ch->casting_spell && cmd_table[cmd].position == POS_FIGHTING )
    {
	if(!is_exact_name(cmd_table[cmd].name, "cast"))
	{
		send_to_char("You are casting a spell, you cannot do anything but 'STOP' (Type stop to cancel spell-casting)\n\r",ch);
		return;
	}
    	return;
    }


in magic.c, do_cast needs to be revamped (just a tad.. i swear ;) )

after the one_argument(target_name, argument); statement, and before
the if(arg1[0]// statement.. put this..

    if (ch->casting_spell == '\0' || ch->casting_spell == FALSE)
    {


now after your 'You can't concentrate enough' statement(Assuming it is
the last one of its kind that determines if you can cast, add this)

	    free_string( ch->casting );
	    ch->casting = str_dup(arg1);
	    free_string( ch->casting2 );
	    ch->casting2 = str_dup(arg2);
	    ch->casting_spell = TRUE;
	    act ("{GYou begin to cast a spell.{x  (type 'stop' to cancel)", ch, NULL, NULL, TO_CHAR);
	    act ("{y$n begins to cast a spell.{x", ch, NULL, NULL, TO_NOTVICT);
	    ch->spell_timer = skill_table[sn].beats;
	    return;
    }

    if (ch->spell_timer != 1)
    {
 	send_to_char("{WYou have to wait to cast the spell you are currently invoking to do that.\r\n", ch);
        return;
    }

    if (arg1[0] == '\0')
    {
        send_to_char ("Cast which what where?\n\r", ch);
        return;
    }


    if ((sn = find_spell(ch,arg1)) < 1
    ||  skill_table[sn].spell_fun == spell_null
    || (!IS_NPC(ch) && (ch->level < skill_table[sn].skill_level[ch->Class]
    || get_skill(ch, sn)   < 1)))

    {
	send_to_char( "You don't know any spells of that name.\n\r", ch );
	return;
    }
  
    if ( ch->position < skill_table[sn].minimum_position )
    {
	send_to_char( "You can't concentrate enough.\n\r", ch );
	return;
    }


Now the last piece, find the WAIT_STATE call within do_cast, the one
that is like WAIT_STATE(ch, skill_table[sn].beats);  i think thats how
it looks, and remove it.. Its nolonger needed.


in merc.h, under struct char_data

place this...

    bool 		casting_spell;
    int 		spell_timer;
    char * 		casting;
    char * 		casting2;



in your prototypes, add the following.

void free_cast(CHAR_DATA *ch);


in recycle.c before new_char  add the following

void free_cast(CHAR_DATA *ch)
{
    ch->casting_spell = FALSE;
    ch->spell_timer = 0;
    free_string(ch->casting);
    free_string(ch->casting2);
}


in new_char  add this with the rest of the setups..

    ch->casting_spell 		= FALSE;
    ch->spell_timer 		= 0;
    ch->casting 		= &str_empty[0];
    ch->casting2 		= &str_empty[0];


in free_char, add the following..

free_cast(ch);


in update.c, right before update_handler, add the following 3 functions.

// The release of the magic, what happens.. now you know!
void act_final(CHAR_DATA *ch)
{
	switch(number_range(0, 4))
	{
		default:
                     act("{RYou chant quietly!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n murmurs something quietly!{x",ch,NULL,NULL,TO_ROOM);
		     return;
		case 1:
                     act("{RThe magical Aura Around you Dissipates as you release your spell!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n{R's magical Aura Dissipates as $e releases $s spell!{x",ch,NULL,NULL,TO_ROOM);
		     return;
		case 2:
                     act("{RThe awesome power of magic flows to your finger-tips!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n{R's power of magic flows through them, surging into their finger-tips!{x",ch,NULL,NULL,TO_ROOM);
		     return;
		case 3:
                     act("{RA Dark aura Whisps around you as your magic releases!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n{R's is surrounded by a dark aura, as $e releases $s magic upon the world!{x",ch,NULL,NULL,TO_ROOM);
		     return;
		case 4:
                     act("{RYour body steams as if you have been boiled, and your magic releases briskly!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n{R's appears to be steaming as $s magic is released briskly!{x",ch,NULL,NULL,TO_ROOM);
		     return;
	}
	return;
}

// Show that your casting (easily expandable!), and should be expanded to make the mud
// more interesting on casting :)
// Created to make magic casting appear finalized, tis always good!  
//                                     -- Dazzle    29/May/2006 7:36
void act_cast(CHAR_DATA *ch)
{
	switch(number_range(0, 6))
	{
		default:
                     act("{RYou chant quietly!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n murmurs something quietly!{x",ch,NULL,NULL,TO_ROOM);
		     return;
		case 1:
                     act("{RYou chant quietly!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n murmurs something quietly!{x",ch,NULL,NULL,TO_ROOM);
		     return;
		case 2:
                     act("{RAs you gesture, magical symbols appear before you!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n waves $s hands around, and mysterious symbols appear!{x",ch,NULL,NULL,TO_ROOM);
		     return;
		case 3:
                     act("{RYou move into a dance like motion as you speak the ancient tongue!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n appears to be dancing and speaking in an odd tongue!{x",ch,NULL,NULL,TO_ROOM);
		     return;
		case 4:
                     act("{RYou levitate slightly as you whisper your magic!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n levitates slightly as $e whispers magical words!{x",ch,NULL,NULL,TO_ROOM);
		     return;
		case 5:
                     act("{RYou bellow a dark incantation!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n bellows a dark incantation!{x",ch,NULL,NULL,TO_ROOM);
		     return;
		case 6:
                     act("{RYou glow slightly as the magic radiates from you!{x",ch,NULL,NULL,TO_CHAR);
                     act("{R$n glows slightly as magic radiates from $m!{x",ch,NULL,NULL,TO_ROOM);
		     return;
	}
	return;
}

// Update the casting system
// This will ensure that all characters will cast their magic
// Its a beautiful thing.
// Simple yes.. Fun yes... Adds Character, you betcha, why not? Cuz!
//                     -- Dazzle      28/May/2006 22:17
void update_casting(void)
{
    CHAR_DATA *ch, *ch_next;
    
    // AWESOME SPELL SYSTEM!
    for (ch = char_list; ch != NULL; ch = ch_next)
    {
        ch_next = ch->next;	// Possible for ch to die, so do it!

	// Booya baby!
        if (ch->spell_timer > 0)
        {
            ch->spell_timer--;
	    if(number_range(0, 7) == 3)
	    	    act_cast(ch);
	}

	// This is what happens to people that cast
        if (ch->spell_timer == 1)
        {
                char buf[MSL];

		// Always display the cast message!
                act_final(ch);
                
                // Ensure we are do not exceed our max (memory-leak protection)
                snprintf(buf, MSL, "%s %s", ch->casting, ch->casting2);

		// Initiate the command
                do_function(ch, &do_cast, buf);
                
                // Free the characters casting data
                free_cast(ch);
                
                // Ensure buf is nul, as to prevent memory leaks (heed my advice!)
                buf[0] = '\0';
        }
    }
    return;
}




in update_handler, right before aggr_update();  add

    update_casting();