#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "emlen.h"
bool
spec_barbarian (CHAR_DATA * ch)
{
CHAR_DATA *victim;
CHAR_DATA *v_next;
if (ch->position != POSITION_FIGHTING)
return FALSE;
for (victim = ch->in_room->more->people; victim != NULL; victim = v_next)
{
v_next = victim->next_in_room;
if (FIGHTING (victim) == ch && number_range (1, 2) == 1)
break;
}
if (victim == NULL)
return FALSE;
if (ch->fgt && ch->fgt->ears > 9)
return FALSE;
if (number_range (1, 3) == 1 && LEVEL (ch) > 25)
{
do_slam (ch, "");
return TRUE;
}
else if (number_range (1, 3) == 1 && LEVEL (ch) > 10)
{
do_headbutt (ch, "");
return TRUE;
}
else
do_bite (ch, "");
return TRUE;
}
SPEC_FUNCTION *
spec_lookup (const char *name)
{
if (!str_cmp (name, "spec_breath_any"))
return spec_breath_any;
if (!str_cmp (name, "spec_breath_acid"))
return spec_breath_acid;
if (!str_cmp (name, "spec_breath_fire"))
return spec_breath_fire;
if (!str_cmp (name, "spec_breath_frost"))
return spec_breath_frost;
if (!str_cmp (name, "spec_breath_gas"))
return spec_breath_gas;
if (!str_cmp (name, "spec_breath_lightning"))
return spec_breath_lightning;
if (!str_cmp (name, "spec_janitor"))
return spec_janitor;
if (!str_cmp (name, "spec_eatcorpse"))
return spec_eatcorpse;
if (!str_cmp (name, "spec_poison"))
return spec_poison;
if (!str_cmp (name, "spec_thief"))
return spec_thief;
if (!str_cmp (name, "spec_warrior"))
return spec_warrior;
if (!str_cmp (name, "spec_barbarian"))
return spec_barbarian;
return NULL;
}
bool
spec_warrior (CHAR_DATA * ch)
{
CHAR_DATA *victim;
CHAR_DATA *v_next;
if (ch->position != POSITION_FIGHTING)
return FALSE;
for (victim = ch->in_room->more->people; victim != NULL; victim = v_next)
{
v_next = victim->next_in_room;
if (FIGHTING (victim) == ch && number_range (1, 2) == 1)
break;
}
if (victim == NULL)
return FALSE;
if (ch->fgt && ch->fgt->ears > 9)
return FALSE;
if (number_range (1, 5) == 1)
{
do_kick (ch, "");
return TRUE;
}
else if (number_range (1, 5) == 1)
{
do_bash (ch, "");
return TRUE;
}
else if (number_range (1, 5) == 1)
{
do_slam (ch, "");
return TRUE;
}
else if (number_range (1, 5) == 1)
{
do_bite (ch, "");
return TRUE;
}
else if (number_range (1, 5) == 1)
{
do_headbutt (ch, "");
return TRUE;
}
else if (ch->move > 45)
do_flurry (ch, "");
return TRUE;
}
/*
* Core procedure for dragons.
*/
bool
dragon (CHAR_DATA * ch, char *spell_name)
{
CHAR_DATA *victim;
CHAR_DATA *v_next;
SPELL_DATA *spll;
if (ch->position != POSITION_FIGHTING)
return FALSE;
for (victim = ch->in_room->more->people; victim != NULL; victim = v_next)
{
v_next = victim->next_in_room;
if (FIGHTING (victim) == ch && number_bits (2) == 0)
break;
}
if (victim == NULL)
return FALSE;
if ((spll = skill_lookup (spell_name, -1)) == NULL)
return FALSE;
general_spell (spll, LEVEL (ch), ch, victim);
return TRUE;
}
/*
* Special procedures for mobiles.
*/
bool
spec_breath_any (CHAR_DATA * ch)
{
if (ch->position != POSITION_FIGHTING)
return FALSE;
switch (number_bits (3))
{
case 0:
return spec_breath_fire (ch);
case 1:
case 2:
return spec_breath_lightning (ch);
case 3:
return spec_breath_gas (ch);
case 4:
return spec_breath_acid (ch);
case 5:
case 6:
case 7:
return spec_breath_frost (ch);
}
return FALSE;
}
bool
spec_breath_acid (CHAR_DATA * ch)
{
return dragon (ch, "acid breath");
}
bool
spec_breath_fire (CHAR_DATA * ch)
{
return dragon (ch, "fire breath");
}
bool
spec_breath_frost (CHAR_DATA * ch)
{
return dragon (ch, "frost breath");
}
bool
spec_breath_gas (CHAR_DATA * ch)
{
SPELL_DATA *spll;
if (ch->position != POSITION_FIGHTING)
return FALSE;
if ((spll = skill_lookup ("gas breath", -1)) == NULL)
return FALSE;
general_spell (spll, LEVEL (ch), ch, NULL);
return TRUE;
}
bool
spec_breath_lightning (CHAR_DATA * ch)
{
return dragon (ch, "lightning breath");
}
bool
spec_executioner (CHAR_DATA * ch)
{
char buf[STD_LENGTH];
CHAR_DATA *victim;
CHAR_DATA *v_next;
if (!IS_AWAKE (ch) || FIGHTING (ch) != NULL)
return FALSE;
for (victim = ch->in_room->more->people; victim != NULL; victim = v_next)
{
v_next = victim->next_in_room;
if (victim->pcdata->bounty >= 40)
break;
}
if (victim == NULL)
return FALSE;
sprintf (buf, "%s is a outlaw! I am the judge and jury! Penalty is death!",
NAME (victim));
do_yell (ch, buf);
multi_hit (ch, victim, TYPE_UNDEFINED);
return TRUE;
}
bool
spec_eatcorpse (CHAR_DATA * ch)
{
SINGLE_OBJECT *corpse;
SINGLE_OBJECT *c_next;
SINGLE_OBJECT *obj;
SINGLE_OBJECT *obj_next;
if (!IS_AWAKE (ch) || FIGHTING (ch) != NULL)
return FALSE;
for (corpse = ch->in_room->more->contents; corpse != NULL; corpse = c_next)
{
c_next = corpse->next_content;
if (corpse->pIndexData->item_type != ITEM_CORPSE_NPC)
continue;
act ("$n begins munching away at the corpse!!", ch, NULL, NULL, TO_ROOM);
for (obj = corpse->contains; obj; obj = obj_next)
{
obj_next = obj->next_content;
obj_from (obj);
obj_to (obj, ch->in_room);
}
free_it (corpse);
return TRUE;
}
return FALSE;
}
bool
spec_guard (CHAR_DATA * ch)
{
char buf[STD_LENGTH];
CHAR_DATA *victim;
if (!IS_AWAKE (ch) || FIGHTING (ch) != NULL)
return FALSE;
if (ch->in_room == NULL)
return FALSE;
for (victim = ch->in_room->more->people; victim != NULL; victim = victim->next_in_room)
{
if (IS_PLAYER (victim) && victim->pcdata->bounty > 20)
break;
}
if (victim != NULL)
{
if (IS_MOB (victim))
return FALSE;
/*change next line if guards should kill outlaws in no-jail zones */
if (get_room_index (victim->in_room->area->jail) == NULL)
return FALSE;
if (number_range (1, 3) == 2)
{
if (victim->pcdata->warned < 5)
{
sprintf (buf, "%s is an outlaw! Surrender or DIE!", NAME (victim));
do_say (ch, buf);
victim->pcdata->warned++;
return TRUE;
}
if (victim->pcdata->warned == 5)
{
sprintf (buf, "This is your last warning, %s! Surrender NOW!", NAME (victim));
do_say (ch, buf);
victim->pcdata->warned++;
return TRUE;
}
if (victim->pcdata->warned > 5)
{
if (FIGHTING (ch) == NULL)
{
sprintf (buf, "Prepare to die, outlaw!");
do_say (ch, buf);
multi_hit (ch, victim, TYPE_UNDEFINED);
}
return TRUE;
}
return TRUE;
}
}
return FALSE;
}
bool
spec_janitor (CHAR_DATA * ch)
{
SINGLE_OBJECT *trash;
SINGLE_OBJECT *trash_next;
if (!IS_AWAKE (ch))
return FALSE;
for (trash = ch->carrying; trash != NULL; trash = trash_next)
{
trash_next = trash->next_content;
switch (trash->pIndexData->item_type)
{
default:
continue;
case ITEM_DRINK_CON:
free_it (trash);
break;
case ITEM_FOOD:
act ("$n eats $p.", ch, trash, NULL, TO_ROOM);
free_it (trash);
break;
}
}
for (trash = ch->in_room->more->contents; trash != NULL; trash = trash_next)
{
trash_next = trash->next_content;
if (!IS_SET (trash->pIndexData->wear_flags, ITEM_TAKE))
continue;
if (trash->pIndexData->item_type == ITEM_DRINK_CON
|| trash->pIndexData->item_type == ITEM_TRASH
|| trash->cost < 10)
{
act ("$n picks up some trash.", ch, NULL, NULL, TO_ROOM);
if (trash->in_room == NULL)
continue;
obj_from (trash);
obj_to (trash, ch);
return TRUE;
}
}
return FALSE;
}
bool
spec_poison (CHAR_DATA * ch)
{
CHAR_DATA *victim;
SPELL_DATA *spl;
if (ch->position != POSITION_FIGHTING
|| !(victim = FIGHTING (ch)) || (FIGHTING (ch) == NULL)
|| number_percent () > 2 * LEVEL (ch))
return FALSE;
act ("You bite $N!", ch, NULL, victim, TO_CHAR);
act ("$n bites $N!", ch, NULL, victim, TO_NOTVICT);
act ("$n bites you!", ch, NULL, victim, TO_VICT);
/*MAKE IT POISON THE PERSON HERE!! */
if ((spl = skill_lookup (NULL, gsn_poison)) == NULL)
return FALSE;
general_spell (spl, LEVEL (ch), ch, victim);
return TRUE;
}
bool
spec_thief (CHAR_DATA * ch)
{
CHAR_DATA *victim;
CHAR_DATA *v_next;
SINGLE_OBJECT *obj, *o_next;
if (ch->position != POSITION_STANDING)
return FALSE;
for (victim = ch->in_room->more->people; victim != NULL; victim = v_next)
{
v_next = victim->next_in_room;
if (IS_MOB (victim))
continue;
if (LEVEL (victim) >= LEVEL_IMMORTAL
|| number_bits (3) != 0
|| !can_see (ch, victim)) /* Thx Glop */
continue;
if (is_safe (ch, victim))
return FALSE;
if (IS_SET (ch->act, ACT_ATTITUDE) && (!IS_AWAKE (victim) || number_range (1, 11) == 2))
{
do_actual_backstab (ch, RNAME (victim));
return TRUE;
}
if (IS_AWAKE (victim)
&& (dice (3, 6) < (get_curr_dex (ch) + get_curr_wis (ch)
- get_curr_wis (victim) - get_curr_dex (victim))))
{
SINGLE_OBJECT *obj;
int chance;
if (victim->pcdata->carry_number == 0)
return FALSE;
chance = 100 / victim->pcdata->carry_number;
for (obj = victim->carrying; obj != NULL; obj = obj->next_content)
{
if ((obj->wear_loc != -1)
|| !can_drop_obj (victim, obj))
continue;
if (number_percent () < chance)
{
obj_from (obj);
obj_to (obj, ch);
if (dice (1, 6) < (get_curr_dex (victim) - get_curr_dex (ch)))
send_to_char ("You feel less burdened.\n\r", victim);
return TRUE;
}
chance += chance;
}
}
else
{
act ("$n tried to steal from you!", ch, NULL, victim, TO_VICT);
}
return FALSE;
}
for (obj = ch->in_room->more->contents; obj != NULL; obj = o_next)
{
int chance;
o_next = obj->next_content;
if (ch->next_in_room == NULL)
chance = 100;
else
chance = 50;
if (obj->pIndexData->item_type == ITEM_CORPSE_NPC
|| obj->pIndexData->item_type == ITEM_CORPSE_PC)
{
SINGLE_OBJECT *obj2;
for (obj2 = obj->contains; obj2 != NULL; obj2 = obj2->next_content)
{
if (IS_SET (obj2->extra_flags, ITEM_NODROP))
continue;
if (number_percent () < chance)
{
obj_from (obj2);
obj_to (obj2, ch);
return TRUE;
}
}
}
else
{
if (!can_see_obj (ch, obj))
continue;
if (!CAN_WEAR (obj, ITEM_TAKE))
continue;
if (number_percent () < chance)
{
if (obj->in_room == NULL)
continue;
obj_from (obj);
obj_to (obj, ch);
return TRUE;
}
}
}
return FALSE;
}