Shield Spell-Group Snippet V1.0

By Tandon Miir, IMP of World of Eternal Dreams
tandonmiir@hotmail.com
http://worldofeternaldreams.tripod.com

Codebase: ROM 2.4x, but port if you know how.

Description:

Force Shield is a defensive spell that gives a slight AC bonus, and randomly 
blocks the attack of an attacker.  The odds of this happening are 
around 1 in 15 hits, so about every 5 or 6 rounds, a "save" will happen.  
The reason this is so low is because it is a relatively low-level spell
on WED.  Modify to your needs.

Static Shield is a defensive spell that randomly casts 'heat metal' on an 
attacker and does light magical damage while blocking the incoming attack. 
Obviously, the spell will only work if the attacker is wearing equipment or 
a weapon. The odds of this ATTEMPT happening are 1 out of every 10 hits, at 
which time, damage will occur, but the success rate of a cast is based on 
the level of the Static Shield Spell...
Modify to your needs.

Flame Shield is a defensive spell that gives the victim an AC bonus, but 
also will randomly harm any attacker that attacks without a wielded weapon.  
The rate of returned damage is about 1 out of every 3 hits, so expect 
around 1 or 2 medium fire attacks per pulse. Modify as needed.

-=INSTALLATION=-

MERC.H

Increment MAX_SKILLS THREE times.

Declare three new AFF bits:

AFF_FORCE_SHIELD
AFF_STATIC_SHIELD
AFF_FLAME_SHIELD


CONST.C

Insert these prototypes into the skill_table struct:

	{
	 "flame shield", {40, 35, 53, 53}, {1, 1, 2, 2},
	 spell_flameshield, TAR_CHAR_SELF, POS_STANDING,
	 NULL, SLOT (550), 40, 12,
	 "flame shield", "The flames surrounding you die away.", ""},

	{
	 "force shield", {20, 15, 53, 53}, {1, 1, 2, 2},
	 spell_forceshield, TAR_CHAR_SELF, POS_STANDING,
	 NULL, SLOT (551), 30, 12,
	 "force shield", "The shield about you fades away.", ""},

	{
	 "static shield", {30, 22, 53, 53}, {1, 1, 2, 2},
	 spell_staticshield, TAR_CHAR_SELF, POS_STANDING,
	 NULL, SLOT (552), 35, 12,
	 "static shield", "The static around you grounds out.", ""},

You can feel free to add them to whatever spell group you want. I have them
under my shielding group (ironically enough).


MAGIC.H

Insert these spell function defines:

DECLARE_SPELL_FUN(  spell_forceshield		);
DECLARE_SPELL_FUN(  spell_staticshield		);
DECLARE_SPELL_FUN(  spell_flameshield		);


MAGIC.C

Now the meat... Put these spell functions in your magic.c in whatever order you like.


void spell_forceshield (int sn, int level, CHAR_DATA * ch, void *vo, int target)
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if (is_affected (victim, sn))
    {
        if (victim == ch)
            send_to_char ("You are already force-shielded.\n\r", ch);
        else
            act ("$N is already force-shielded.", ch, NULL, victim,
                 TO_CHAR);
        return;
    }

    af.where = TO_AFFECTS;
    af.type = sn;
    af.level = level;
    af.duration = level / 4;
    af.location = APPLY_AC;
    af.modifier = (level / 5) * -1;
    af.bitvector = AFF_FORCE_SHIELD;
    affect_to_char (victim, &af);
    act ("A sparkling force-shield encircles $n.", victim, NULL, NULL, TO_ROOM);
    send_to_char ("You are encircled by a sparkling force-shield.\n\r", victim);
    return;
}

void spell_staticshield (int sn, int level, CHAR_DATA * ch, void *vo, int target)
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if (is_affected (victim, sn))
    {
        if (victim == ch)
            send_to_char ("You are surrounded by static charge.\n\r", ch);
        else
            act ("$N is already surrounded by static charge.", ch, NULL, victim,
                 TO_CHAR);
        return;
    }

    af.where = TO_AFFECTS;
    af.type = sn;
    af.level = level;
    af.duration = level / 3;
    af.location = APPLY_AC;
    af.modifier = (level / 4) * -1;
    af.bitvector = AFF_STATIC_SHIELD;
    affect_to_char (victim, &af);
    act ("$n is surrounded by a pulse of static charge.", victim, NULL, NULL, TO_ROOM);
    send_to_char ("You are surrounded by a pulse of static charge.\n\r", victim);
    return;
}

void spell_flameshield (int sn, int level, CHAR_DATA * ch, void *vo, int target)
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if (is_affected (victim, sn))
    {
        if (victim == ch)
            send_to_char ("You are already protected by fire.\n\r", ch);
        else
            act ("$N is already protected by fire.", ch, NULL, victim,
                 TO_CHAR);
        return;
    }

    af.where = TO_AFFECTS;
    af.type = sn;
    af.level = level;
    af.duration = (level / 10);
    af.location = APPLY_AC;
    af.modifier = (level / 2) * -1;
    af.bitvector = AFF_FLAME_SHIELD;
    affect_to_char (victim, &af);
    act ("$n is shielded by red walls of flame.", victim, NULL, NULL, TO_ROOM);
    send_to_char ("You are shielded by red walls of flame.\n\r", victim);
    return;
}

FIGHT.C

Now to make them all work.  In fight.c, place these three function prototypes at the top.

bool check_force_shield args ( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
bool check_static_shield args ( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
bool check_flame_shield args ( ( CHAR_DATA *ch, CHAR_DATA *victim ) );

Place "magic.h" in the includes if it isn't already there.  This will allow us to call 
spell effects from functions.

Somewhere in fight.c put in these functions:

/*
 *  Shield Spell Group by Tandon
 *  Force Shield Check
 */

bool check_force_shield( CHAR_DATA *ch, CHAR_DATA *victim )
{
    int chance;

	if(!IS_AFFECTED(victim, AFF_FORCE_SHIELD))
		return FALSE;

    chance = 100 / 15;

    if (victim->level >= ch->level)
	chance += 2;

    if ( number_percent( ) >= chance )
        return FALSE;

    act("Your force-shield blocks $n's attack!", ch, NULL, victim, TO_VICT);
    act("$N's force-shield blocks your attack.", ch, NULL, victim, TO_CHAR);

    return TRUE;
}

/*
 *  Shield Spell Group by Tandon
 *  Static Shield Check
 */

bool check_static_shield( CHAR_DATA *ch, CHAR_DATA *victim )
{
    int chance, sn;
	AFFECT_DATA *shock;

	if(!IS_AFFECTED(victim, AFF_STATIC_SHIELD))
		return FALSE;

    chance = 10;

    if (victim->level >= ch->level)
	chance += 2;

    if ( number_percent( ) >= chance )
        return FALSE;

    
	sn = skill_lookup( "static shield" );
	shock = affect_find (victim->affected, sn);
	
	if(shock != NULL)
	{
		damage (victim, ch, number_fuzzy(shock->level / 5), sn, DAM_ENERGY, TRUE);
	}

    if (get_eq_char (ch, WEAR_WIELD) == NULL)
		return TRUE;

    act("Your static shield catches $n!", victim, NULL, ch, TO_VICT);
    act("$N's static shield catches you!", victim, NULL, ch, TO_CHAR);
    
	spell_heat_metal (skill_lookup( "heat metal" ),
                     victim->level/2, victim, (void *) ch, TARGET_CHAR);		

    return TRUE;
}

/*
 *  Shield Spell Group by Tandon
 *  Flame Shield Check
 */

bool check_flame_shield( CHAR_DATA *ch, CHAR_DATA *victim )
{
    int chance, sn;
	AFFECT_DATA *burn;

	if(!IS_AFFECTED(victim, AFF_FLAME_SHIELD))
		return FALSE;

    if (get_eq_char (victim, WEAR_WIELD) != NULL)
		return FALSE;

    chance = 100 / 3;

    if (victim->level >= ch->level)
	chance += 2;

    if ( number_percent( ) >= chance )
        return FALSE;

	sn = skill_lookup( "flame shield" );
	burn = affect_find (victim->affected, sn);
	
	if(burn != NULL)
	{   
		fire_effect (ch, burn->level, number_fuzzy(10), TARGET_CHAR);
		damage (victim, ch, number_fuzzy(burn->level), sn, DAM_FIRE, TRUE);
	}

    return TRUE;
}

In the function damage...  Right after this:

      if (check_parry (ch, victim))
            return FALSE;
      if (check_dodge (ch, victim))
            return FALSE;
      if (check_shield_block (ch, victim))
            return FALSE;

Add WITHIN the brackets.

	if(IS_AFFECTED (victim, AFF_FORCE_SHIELD) && check_force_shield(ch, victim))
		return FALSE;
	if(IS_AFFECTED (victim, AFF_STATIC_SHIELD) && check_static_shield(ch, victim))
		return FALSE;

And right after those checks and OUTSIDE the brackets, place this:

// If taking damage, check if attacker gets burned -- Tandon

	if(IS_AFFECTED (victim, AFF_FLAME_SHIELD) && dam_type <= 3)
		check_flame_shield(ch, victim);


If you want to be able to dispel or cancel these spells... Add these under
spell_cancellation and spell_dispel_magic

	if (check_dispel (level, victim, skill_lookup ("force shield")))
    {
        act ("The force-shield encircling $n fades.", victim, NULL, NULL,
             TO_ROOM);
        found = TRUE;
    }


	if (check_dispel (level, victim, skill_lookup ("static shield")))
    {
        act ("The static energy surrounding $n dissipates.", victim, NULL, NULL,
             TO_ROOM);
        found = TRUE;
    }


	if (check_dispel (level, victim, skill_lookup ("flame shield")))
    {
        act ("The flames protecting $n sputter and die.", victim, NULL, NULL,
             TO_ROOM);
        found = TRUE;
    }

That's it.
Enjoy.  

Tandon

tandonmiir@hotmail.com
worldofeternaldreams.tripod.com